第 29 条:遵循 Clippy 的建议
“看起来你在写信。需要什么帮助么?” —— [Microsoft Clippit]
第 31 条会描述了 Rust 工具箱中一些很有用的工具。但是其中一个特别有用且重要的工具值的在这里进行进行单独的介绍:Clippy。
Clippy 是 Cargo 的一个附加模块(通过cargo clippy
的方式调用)。它可以生成涵盖多种类别的warining
信息:
- 正确性:提示常见的编程错误。
- 风格:提示不完全符合 Rust 标准风格的代码结构。
- 简洁性:指出能让代码更加简洁的可行变更。
- 性能:提示能避免无效处理或者内存分配的可选项。
- 可读性:给出能让代码更易读或者更易懂的建议。
比如,如下这段代码编译是正常的:
#![allow(unused)] fn main() { pub fn circle_area(radius: f64) -> f64 { let pi = 3.14; pi * radius * radius } }
但是 Clippy 会指出这里对 π 的近似赋值是没必要且不准确的:
#![allow(unused)] fn main() { error: approximate value of `f{32, 64}::consts::PI` found --> src/main.rs:5:18 | 5 | let pi = 3.14; | ^^^^ | = help: consider using the constant directly = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant = note: `#[deny(clippy::approx_constant)]` on by default }
链接中的文档解释了问题并且给出了优化代码的方式。上述示例可调整为:
#![allow(unused)] fn main() { pub fn circle_area(radius: f64) -> f64 { std::f64::consts::PI * radius * radius } }
正如示例中所展示的,每个 Clippy 警告都会伴随着一个网页的链接来描述问题。链接的网页中会说明为什么目标代码会被认为是不恰当的。这些说明很重要:它们的存在使得你可以自行判断采纳这些建议或者由于特殊的原因而忽略它们。有的时候,说明文本中还会描述一些校验器的已知问题,这些描述会解释一些令人困惑的误报。
如果你认定一些警告信息和自己的代码没有关系,你可以通过添加(#[allow(clippy::some_line)])来忽略关联代码的报错,或者在包的顶层(top level)添加(#![allow(clipy::some_lint)])来忽略整个包中的警告信息。通常情况下,建议调整目标代码而非花费很多时间来确认警告关联的代码是否是一个罕见的误报。
无论你选择了修复或者忽略掉这些警告信息,请确保你的代码中没有 Clippy-warning 的信息。
这样,当新的警告信息出现时 —— 无论是由于代码发生了调整还是 Clippy 升级后包含了新的校验信息 —— 我们就能够及时的关注到。Clippy 也应当被纳入你的持续集成系统中(第 32 条)。
Clippy 的警告信息在你学习 Rust 时特别重要,因为它们可以揭示那些被你忽略的细节,并帮助你熟悉 Rust 的风格。
本书中提到的很多建议,在 Clippy 中均存在相关的警告信息:
- 第 1 条建议使用更具表现力的类型,而非一般的
bool
类型。Clippy 也指出了在函数参数以及结构体中使用多个bool
类型的问题。 - 第 3 条包括了一些
Option
及Result
类型的操作。Clippy 指出了一些可行的精简行为,比如: - 第 3 条同样建议了应当将错误返回给调用方。Clippy [指出了应当返回的地方]。
- 第 5 条应当实现
From
特征而非Into
。 - 第 5 条还描述了一些强制转换,而 Clippy 给出了如下的警告(对应的检查项默认是关掉的):
- 第 8 条描述了胖指针类型,并且很多 Clippy 的校验器指出了一些非必要的额外的指针间接访问:
- 第 9 条描述了操作
Iterator
实例的诸多方法。Clippy 包含了诸多的可以简化迭代器方法使用的校验器1。 - 第 10 条描述了 Rust 的标准特性,并且包含了很多 Clippy 会校验到的实现时的要求:
- 第 18 条提供了一些关于减少
panic!
或类似expect
的方法,这些建议也会在 Clippy 的校验器中检查到。 - 第 21 条表述了引入通过通配符限定的包是不明智的。Clippy 同样对此进行了校验。
- 第 23 条及第 25 条涉及到一种不同版本的包出现在同一个项目的依赖中。Clippy 可以通过配置,在问题出现时给出警告信息。
- 第 26 条叙述了 Cargo 特性的一些相加性,而 Clippy 会将与此原则相违背特性提示为“否定”的特性。
- 第 26 条同样表述了一个包的可选依赖项同样是其特征集的一部分。如果存在需要明确的特性名(如:"use-crate-x"形式的命名)时,Clippy 将会提示直接应当使用明确的特性名,而非模糊的。
- 第 27 条描述了文档注释的约束,Clippy 同时有如下的提示:
上述的信息无疑说明了阅读 Clippy 的警告信息列表同样是一种有意义的学习方式 —— 包括那些默认被关掉校验的原因,是由于它们太严苛了还是由于它们会产生虚警?尽管你可能并不希望代码中出现这么多的警告信息,领悟这些校验规则出现的原因将会提升你对 Rust 及其风格的理解。
注释
部分校验器列举如下。explicit_counter_loop,explicit_iter_loop,explicit_into_iter_loop,filter_map_identity,from_iter_instead_of_collect,into_iter_on_ref,iter_count,iter_next_loop,iter_not_returning_iterator,manual_filter_map,manual_find_map,map_clone,needless_range_loop,search_is_some,skip_while_next,suspicious_map,unnecessary_filter_map,unnecessary_fold。
原文点这里查看