默认允许的 Lint

这些 Lint 默认都设置为 'allow' 等级。因此,除非您使用标志或属性将它们设置为更高的 Lint 等级,否则它们不会出现。

absolute-paths-not-starting-with-crate

absolute_paths_not_starting_with_crate Lint 检测以模块名称而不是 crateself 或外部 crate 名称开头的完全限定路径

示例

#![deny(absolute_paths_not_starting_with_crate)]

mod foo {
    pub fn bar() {}
}

fn main() {
    ::foo::bar();
}

这将产生

error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
 --> lint_example.rs:8:5
  |
8 |     ::foo::bar();
  |     ^^^^^^^^^^ help: use `crate`: `crate::foo::bar`
  |
  = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
  = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(absolute_paths_not_starting_with_crate)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

Rust 版本 允许语言在不破坏向后兼容性的情况下发展。此 Lint 捕获使用 2015 版本风格的绝对路径的代码。在 2015 版本中,绝对路径(以 :: 开头)指的是 crate 根目录或外部 crate。在 2018 版本中,它被更改为仅指外部 crate。路径前缀 crate:: 应该用于引用 crate 根目录中的项目。

如果您在不更新代码的情况下将编译器从 2015 版本切换到 2018 版本,那么如果使用旧风格的路径,它将无法编译。您可以手动更改路径以使用 crate:: 前缀来过渡到 2018 版本。

此 Lint 自动解决了这个问题。它默认是 "allow",因为代码在 2015 版本中是完全有效的。带有 --edition 标志的 cargo fix 工具将把此 Lint 切换到 "warn" 并自动应用编译器建议的修复。这提供了一种完全自动化的方式来将旧代码更新到 2018 版本。

async-idents

Lint async-idents 已重命名为 keyword-idents

box-pointers

box_pointers Lint 使用 Box 类型。

示例

#![deny(box_pointers)]
struct Foo {
    x: Box<isize>,
}

这将产生

error: type uses owned (Box type) pointers: Box<isize>
 --> lint_example.rs:4:5
  |
4 |     x: Box<isize>,
  |     ^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(box_pointers)]
  |         ^^^^^^^^^^^^

解释

此 Lint 主要是有历史意义的,并不是特别有用。Box<T> 曾经是内置在语言中的,并且是进行堆分配的唯一方法。如今的 Rust 可以调用其他分配器等。

dereferencing-mut-binding

dereferencing_mut_binding Lint 检测到一个 mut x 模式,它会重置绑定模式,因为这种行为将在 rust 2024 中发生变化。

示例

#![warn(dereferencing_mut_binding)]
let x = Some(123u32);
let _y = match &x {
    Some(mut x) => {
        x += 1;
        x
    }
    None => 0,
};

这将产生

warning: unknown lint: `dereferencing_mut_binding`
 --> lint_example.rs:1:1
  |
1 | #![warn(dereferencing_mut_binding)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: the `dereferencing_mut_binding` lint is unstable
  = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
  = help: add `#![feature(mut_preserve_binding_mode_2024)]` to the crate attributes to enable
  = note: this compiler was built on 2024-06-10; consider upgrading it if it is out of date
  = note: `#[warn(unknown_lints)]` on by default

解释

如果没有 mutx 的类型将是 &u32。在 2024 年之前,添加 mut 会使 x 的类型变为 u32,这被认为是令人惊讶的。在 2024 版本之后,添加 mut 不会改变 x 的类型。此 Lint 警告 2024 版本之前的用户更新他们的代码。

disjoint-capture-migration

Lint disjoint-capture-migration 已重命名为 rust-2021-incompatible-closure-captures

elided-lifetime-in-path

Lint elided-lifetime-in-path 已重命名为 elided-lifetimes-in-paths

elided-lifetimes-in-paths

elided_lifetimes_in_paths Lint 检测隐藏的生命周期参数的使用。

示例

#![deny(elided_lifetimes_in_paths)]
#![deny(warnings)]
struct Foo<'a> {
    x: &'a u32
}

fn foo(x: &Foo) {
}

这将产生

error: hidden lifetime parameters in types are deprecated
 --> lint_example.rs:8:12
  |
8 | fn foo(x: &Foo) {
  |            ^^^ expected lifetime parameter
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(elided_lifetimes_in_paths)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^
help: indicate the anonymous lifetime
  |
8 | fn foo(x: &Foo<'_>) {
  |               ++++

解释

隐藏的生命周期参数可能难以一眼看出正在发生借用。此 Lint 确保生命周期参数始终明确声明,即使是 '_ 占位符生命周期

此 Lint 默认是 "allow",因为它有一些已知问题,并且可能需要对旧代码进行重大过渡。

explicit-outlives-requirements

explicit_outlives_requirements Lint 检测不必要的生命周期边界,这些边界可以被推断出来。

示例

#![allow(unused)]
#![deny(explicit_outlives_requirements)]
#![deny(warnings)]

struct SharedRef<'a, T>
where
    T: 'a,
{
    data: &'a T,
}

这将产生

error: outlives requirements can be inferred
 --> lint_example.rs:6:24
  |
6 |   struct SharedRef<'a, T>
  |  ________________________^
7 | | where
8 | |     T: 'a,
  | |__________^ help: remove this bound
  |
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![deny(explicit_outlives_requirements)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

如果一个 struct 包含一个引用,例如 &'a T,编译器要求 T 比生命周期 'a 更长。历史上,这需要编写一个明确的生命周期边界来表明这个要求。但是,这可能过于明确,导致混乱和不必要的复杂性。语言被更改为自动推断边界,如果它没有被指定。具体来说,如果该 struct 直接或间接地包含对 T 的引用,其生命周期为 'x,那么它将推断 T: 'x 是一个要求。

此 Lint 默认是 "allow",因为它对于已经具有这些要求的现有代码来说可能很吵。这是一个风格选择,因为明确声明边界仍然是有效的。它也有一些误报,可能会造成混淆。

有关更多详细信息,请参阅 RFC 2093

ffi-unwind-calls

ffi_unwind_calls Lint 检测对使用 C-unwind 或其他 FFI-unwind ABI 的外部函数或函数指针的调用。

示例

#![warn(ffi_unwind_calls)]

extern "C-unwind" {
    fn foo();
}

fn bar() {
    unsafe { foo(); }
    let ptr: unsafe extern "C-unwind" fn() = foo;
    unsafe { ptr(); }
}

这将产生

warning: call to foreign function with FFI-unwind ABI
 --> lint_example.rs:9:14
  |
9 |     unsafe { foo(); }
  |              ^^^^^ call to foreign function with FFI-unwind ABI
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(ffi_unwind_calls)]
  |         ^^^^^^^^^^^^^^^^


warning: call to function pointer with FFI-unwind ABI
  --> lint_example.rs:11:14
   |
11 |     unsafe { ptr(); }
   |              ^^^^^ call to function pointer with FFI-unwind ABI

解释

对于包含此类调用的 crate,如果它们使用 -C panic=unwind 编译,那么生成的库将无法与使用 -C panic=abort 编译的 crate 链接。因此,对于希望具有此功能的 crate,有必要避免此类调用。

fuzzy-provenance-casts

fuzzy_provenance_casts Lint 检测整数和指针之间的 as 转换。

示例

#![feature(strict_provenance)]
#![warn(fuzzy_provenance_casts)]

fn main() {
    let _dangling = 16_usize as *const u8;
}

这将产生

warning: strict provenance disallows casting integer `usize` to pointer `*const u8`
 --> lint_example.rs:5:21
  |
5 |     let _dangling = 16_usize as *const u8;
  |                     ^^^^^^^^^^^^^^^^^^^^^
  |
  = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![warn(fuzzy_provenance_casts)]
  |         ^^^^^^^^^^^^^^^^^^^^^^
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
  |
5 |     let _dangling = (...).with_addr(16_usize);
  |                     ++++++++++++++++        ~

解释

此 Lint 是严格来源工作的一部分,请参阅 问题 #95228。将整数转换为指针被认为是不好的风格,因为指针除了包含地址之外,还包含来源,指示指针允许读写哪些内存。将没有来源的整数转换为指针要求编译器分配(猜测)来源。编译器分配 "所有暴露的有效"(有关此 "暴露" 的更多信息,请参阅 ptr::with_exposed_provenance 的文档)。这会惩罚优化器,并且不适合动态分析/动态程序验证(例如 Miri 或 CHERI 平台)。

最好使用 ptr::with_addr 来指定您想要的来源。如果由于代码依赖于暴露的来源而无法使用此函数,那么可以使用 ptr::with_exposed_provenance 作为一种逃生舱。

keyword-idents

Lint keyword-idents 已重命名为 keyword-idents-2018

keyword-idents-2018

keyword_idents_2018 Lint 检测到版本关键字被用作标识符。

示例

#![deny(keyword_idents_2018)]
// edition 2015
fn dyn() {}

这将产生

error: `dyn` is a keyword in the 2018 edition
 --> lint_example.rs:4:4
  |
4 | fn dyn() {}
  |    ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
  |
  = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
  = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(keyword_idents_2018)]
  |         ^^^^^^^^^^^^^^^^^^^

解释

Rust 版本 允许语言在不破坏向后兼容性的情况下演进。此 lint 捕获使用作为标识符(例如变量名、函数名等)的新关键字的代码。如果您将编译器切换到新版本而没有更新代码,那么如果您使用新关键字作为标识符,它将无法编译。

您可以手动将标识符更改为非关键字,或使用 原始标识符,例如 r#dyn,以过渡到新版本。

此 lint 自动解决问题。它默认情况下是“允许”的,因为代码在旧版本中是完全有效的。带有 --edition 标志的 cargo fix 工具将把此 lint 切换为“警告”,并自动应用编译器建议的修复(即使用原始标识符)。这提供了一种完全自动化的方式来更新旧代码以适应新版本。

keyword-idents-2024

keyword_idents_2024 lint 检测作为标识符使用的版本关键字。

示例

#![deny(keyword_idents_2024)]
// edition 2015
fn gen() {}

这将产生

error: `gen` is a keyword in the 2024 edition
 --> lint_example.rs:4:4
  |
4 | fn gen() {}
  |    ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
  |
  = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
  = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(keyword_idents_2024)]
  |         ^^^^^^^^^^^^^^^^^^^

解释

Rust 版本 允许语言在不破坏向后兼容性的情况下演进。此 lint 捕获使用作为标识符(例如变量名、函数名等)的新关键字的代码。如果您将编译器切换到新版本而没有更新代码,那么如果您使用新关键字作为标识符,它将无法编译。

您可以手动将标识符更改为非关键字,或使用 原始标识符,例如 r#gen,以过渡到新版本。

此 lint 自动解决问题。它默认情况下是“允许”的,因为代码在旧版本中是完全有效的。带有 --edition 标志的 cargo fix 工具将把此 lint 切换为“警告”,并自动应用编译器建议的修复(即使用原始标识符)。这提供了一种完全自动化的方式来更新旧代码以适应新版本。

let-underscore-drop

let_underscore_drop lint 检查没有将具有非平凡 Drop 实现的表达式绑定到任何内容的语句,导致表达式立即被丢弃,而不是在作用域结束时被丢弃。

示例

struct SomeStruct;
impl Drop for SomeStruct {
    fn drop(&mut self) {
        println!("Dropping SomeStruct");
    }
}

fn main() {
   #[warn(let_underscore_drop)]
    // SomeStruct is dropped immediately instead of at end of scope,
    // so "Dropping SomeStruct" is printed before "end of main".
    // The order of prints would be reversed if SomeStruct was bound to
    // a name (such as "_foo").
    let _ = SomeStruct;
    println!("end of main");
}

这将产生

warning: non-binding let on a type that implements `Drop`
  --> lint_example.rs:14:5
   |
14 |     let _ = SomeStruct;
   |     ^^^^^^^^^^^^^^^^^^^
   |
note: the lint level is defined here
  --> lint_example.rs:9:11
   |
9  |    #[warn(let_underscore_drop)]
   |           ^^^^^^^^^^^^^^^^^^^
help: consider binding to an unused variable to avoid immediately dropping the value
   |
14 |     let _unused = SomeStruct;
   |         ~~~~~~~
help: consider immediately dropping the value
   |
14 |     drop(SomeStruct);
   |     ~~~~~          +

解释

将表达式分配给下划线的语句会导致表达式立即被丢弃,而不是将表达式的生命周期扩展到作用域的末尾。这通常是无意的,特别是对于像 MutexGuard 这样的类型,它们通常用于在整个作用域内锁定互斥锁。

如果您想将表达式的生命周期扩展到作用域的末尾,请将一个以下划线开头的名称(例如 _foo)分配给表达式。如果您确实想立即丢弃表达式,那么在表达式上调用 std::mem::drop 更清晰,有助于传达意图。

lossy-provenance-casts

lossy_provenance_casts lint 检测指针和整数之间的 as 转换。

示例

#![feature(strict_provenance)]
#![warn(lossy_provenance_casts)]

fn main() {
    let x: u8 = 37;
    let _addr: usize = &x as *const u8 as usize;
}

这将产生

warning: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
 --> lint_example.rs:6:24
  |
6 |     let _addr: usize = &x as *const u8 as usize;
  |                        ^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![warn(lossy_provenance_casts)]
  |         ^^^^^^^^^^^^^^^^^^^^^^
help: use `.addr()` to obtain the address of a pointer
  |
6 |     let _addr: usize = (&x as *const u8).addr();
  |                        +               ~~~~~~~~

解释

此 lint 是严格来源工作的一部分,请参阅 问题 #95228。将指针转换为整数是一个有损操作,因为除了地址之外,指针可能还与特定的来源相关联。此信息由优化器以及动态分析/动态程序验证(例如 Miri 或 CHERI 平台)使用。

由于此转换是有损的,因此建议使用 ptr::addr 方法,它具有类似的效果,但不“暴露”指针来源。这提高了优化潜力。有关暴露指针来源的更多信息,请参阅 ptr::addrptr::expose_provenance 的文档。

如果您的代码无法遵守严格的来源并且需要暴露来源,那么可以使用 ptr::expose_provenance 作为一种逃生舱口,它保留了 as usize 转换的行为,同时明确了语义。

macro-use-extern-crate

macro_use_extern_crate lint 检测 macro_use 属性 的使用。

示例

#![deny(macro_use_extern_crate)]

#[macro_use]
extern crate serde_json;

fn main() {
    let _ = json!{{}};
}

这将产生

error: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
 --> src/main.rs:3:1
  |
3 | #[macro_use]
  | ^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> src/main.rs:1:9
  |
1 | #![deny(macro_use_extern_crate)]
  |         ^^^^^^^^^^^^^^^^^^^^^^

解释

extern crate 项目上的 macro_use 属性 会导致该外部 crate 中的宏被引入 crate 的 prelude 中,使宏在任何地方都有效。作为简化 2018 版本 中依赖项处理工作的一部分,extern crate 的使用正在逐步淘汰。要将外部 crate 中的宏引入作用域,建议使用 use 导入

此 lint 默认情况下是“允许”的,因为这是一个尚未确定的风格选择,请参阅 问题 #52043 以获取更多信息。

meta-variable-misuse

meta_variable_misuse lint 检测宏定义中可能的元变量误用。

示例

#![deny(meta_variable_misuse)]

macro_rules! foo {
    () => {};
    ($( $i:ident = $($j:ident),+ );*) => { $( $( $i = $k; )+ )* };
}

fn main() {
    foo!();
}

这将产生

error: unknown macro variable `k`
 --> lint_example.rs:5:55
  |
5 |     ($( $i:ident = $($j:ident),+ );*) => { $( $( $i = $k; )+ )* };
  |                                                       ^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(meta_variable_misuse)]
  |         ^^^^^^^^^^^^^^^^^^^^

解释

有许多不同的方法可以错误地定义 macro_rules 宏。许多这些错误以前只在宏扩展时或根本没有检测到。此 lint 试图在定义宏时捕获其中一些问题。

此 lint 默认情况下是“允许”的,因为它可能存在误报和其他问题。有关更多详细信息,请参阅 问题 #61053

missing-abi

missing_abi lint 检测在 extern 声明中省略 ABI 的情况。

示例

#![deny(missing_abi)]

extern fn foo() {}

这将产生

error: extern declarations without an explicit ABI are deprecated
 --> lint_example.rs:4:1
  |
4 | extern fn foo() {}
  | ^^^^^^^^^^^^^^^ ABI should be specified here
  |
  = help: the default ABI is C
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(missing_abi)]
  |         ^^^^^^^^^^^

解释

从历史上看,Rust 隐式地为 extern 声明选择 C 作为 ABI。我们预计将来会添加新的 ABI,例如 C-unwind,尽管这还没有发生,特别是随着它们的添加,轻松查看 ABI 将使代码审查更容易。

missing-copy-implementations

missing_copy_implementations lint 检测可能被遗忘的 Copy 实现,用于公共类型。

示例

#![deny(missing_copy_implementations)]
pub struct Foo {
    pub field: i32
}
fn main() {}

这将产生

error: type could implement `Copy`; consider adding `impl Copy`
 --> lint_example.rs:2:1
  |
2 | / pub struct Foo {
3 | |     pub field: i32
4 | | }
  | |_^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(missing_copy_implementations)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

从历史上看(在 1.0 之前),如果可能,类型会自动标记为 Copy。这已更改,因此它需要通过实现 Copy 特性来明确选择加入。作为此更改的一部分,添加了一个 lint 来提醒如果可复制类型未标记为 Copy

此 lint 默认情况下是“允许”的,因为此代码并不糟糕;通常会这样编写 newtype,以便 Copy 类型不再是 CopyCopy 类型会导致意外复制大量数据,这会影响性能。

missing-debug-implementations

missing_debug_implementations lint 检测 fmt::Debug 的缺失实现,用于公共类型。

示例

#![deny(missing_debug_implementations)]
pub struct Foo;
fn main() {}

这将产生

error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
 --> lint_example.rs:2:1
  |
2 | pub struct Foo;
  | ^^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(missing_debug_implementations)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

在所有类型上都有一个 Debug 实现可以帮助调试,因为它提供了一种方便的方式来格式化和显示值。使用 #[derive(Debug)] 属性将自动生成一个典型的实现,或者可以通过手动实现 Debug 特性来添加一个自定义实现。

此 lint 默认情况下是“允许”的,因为将 Debug 添加到所有类型可能会对编译时间和代码大小产生负面影响。它还要求在每个类型中添加样板代码,这可能是一个障碍。

missing-docs

missing_docs lint 检测公共项目缺少文档。

示例

#![deny(missing_docs)]
pub fn foo() {}

这将产生

error: missing documentation for the crate
 --> lint_example.rs:1:1
  |
1 | / #![deny(missing_docs)]
2 | | fn main() {
3 | | pub fn foo() {}
4 | | }
  | |_^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(missing_docs)]
  |         ^^^^^^^^^^^^

解释

此 lint 旨在确保库有良好的文档。没有文档的项目可能难以让用户理解如何正确使用。

此 lint 默认情况下是“允许”的,因为它可能很吵闹,并非所有项目都希望强制执行所有内容都必须有文档。

multiple-supertrait-upcastable

multiple_supertrait_upcastable lint 检测当一个对象安全特性有多个超特性时。

示例

#![feature(multiple_supertrait_upcastable)]
trait A {}
trait B {}

#[warn(multiple_supertrait_upcastable)]
trait C: A + B {}

这将产生

warning: `C` is object-safe and has multiple supertraits
 --> lint_example.rs:7:1
  |
7 | trait C: A + B {}
  | ^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:6:8
  |
6 | #[warn(multiple_supertrait_upcastable)]
  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

为了支持使用多个超特性进行向上转换,我们需要存储多个 vtable,这会导致额外的空间开销,即使没有代码实际使用向上转换。此 lint 允许用户识别何时发生这种情况,并决定额外的开销是否合理。

must-not-suspend

must_not_suspend lint 防止在挂起点(.await)之间持有不应该被持有的值。

示例

#![feature(must_not_suspend)]
#![warn(must_not_suspend)]

#[must_not_suspend]
struct SyncThing {}

async fn yield_now() {}

pub async fn uhoh() {
    let guard = SyncThing {};
    yield_now().await;
    let _guard = guard;
}

这将产生

warning: `SyncThing` held across a suspend point, but should not be
  --> lint_example.rs:11:9
   |
11 |     let guard = SyncThing {};
   |         ^^^^^
12 |     yield_now().await;
   |                 ----- the value is held across this suspend point
   |
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
  --> lint_example.rs:11:9
   |
11 |     let guard = SyncThing {};
   |         ^^^^^
note: the lint level is defined here
  --> lint_example.rs:2:9
   |
2  | #![warn(must_not_suspend)]
   |         ^^^^^^^^^^^^^^^^

解释

must_not_suspend lint 检测标记为 #[must_not_suspend] 属性的值在挂起点之间被持有。“挂起”点通常是异步函数中的 .await

此属性可用于标记在挂起时语义上不正确的值(例如某些类型的计时器)、具有异步替代方案的值以及经常导致异步 fn 返回的 future 的 Send 性出现问题的值(例如 MutexGuard)。

non-ascii-idents

non_ascii_idents lint 检测非 ASCII 标识符。

示例

#![allow(unused)]
#![deny(non_ascii_idents)]
fn main() {
    let föö = 1;
}

这将产生

error: identifier contains non-ASCII characters
 --> lint_example.rs:4:9
  |
4 |     let föö = 1;
  |         ^^^
  |
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![deny(non_ascii_idents)]
  |         ^^^^^^^^^^^^^^^^

解释

此 lint 允许希望保留仅使用 ASCII 字符的限制的项目将此 lint 切换为“禁止”(例如,为了简化协作或出于安全原因)。有关更多详细信息,请参阅 RFC 2457

non-exhaustive-omitted-patterns

non_exhaustive_omitted_patterns lint 旨在帮助 #[non_exhaustive] 结构或枚举的使用者,他们希望显式匹配其所有字段/变体。

#[non_exhaustive] 注释强制匹配使用通配符,因此无法使用穷举检查来确保显式匹配所有字段/变体。为了解决这个问题,此允许默认的 lint 在匹配提到 #[non_exhaustive] 结构或枚举的某些字段/变体,但不是全部时,会向用户发出警告。

示例

// crate A
#[non_exhaustive]
pub enum Bar {
    A,
    B, // added variant in non breaking change
}

// in crate B
#![feature(non_exhaustive_omitted_patterns_lint)]
#[warn(non_exhaustive_omitted_patterns)]
match Bar::A {
    Bar::A => {},
    _ => {},
}

这将产生

warning: some variants are not matched explicitly
   --> $DIR/reachable-patterns.rs:70:9
   |
LL |         match Bar::A {
   |               ^ pattern `Bar::B` not covered
   |
 note: the lint level is defined here
  --> $DIR/reachable-patterns.rs:69:16
   |
LL |         #[warn(non_exhaustive_omitted_patterns)]
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = help: ensure that all variants are matched explicitly by adding the suggested match arms
   = note: the matched value is of type `Bar` and the `non_exhaustive_omitted_patterns` attribute was found

警告:将此设置为 deny 将导致上游非破坏性更改(向 #[non_exhaustive] 结构或枚举添加字段或变体)破坏您的 crate。这违反了预期的 semver 行为。

解释

标记为 #[non_exhaustive] 的结构和枚举强制用户在模式匹配时添加一个(可能冗余的)通配符,以允许将来添加字段或变体。non_exhaustive_omitted_patterns lint 检测到当此类通配符恰好实际捕获了一些字段/变体时。换句话说,当没有通配符的匹配将不是穷举的时。这可以让用户知道是否添加了新的字段/变体。

non-local-definitions

non_local_definitions lint 检查 impl 块和 #[macro_export] 宏在主体(函数、枚举判别式、...)内部。

示例

#![warn(non_local_definitions)]
trait MyTrait {}
struct MyStruct;

fn foo() {
    impl MyTrait for MyStruct {}
}

这将产生

warning: non-local `impl` definition, they should be avoided as they go against expectation
 --> lint_example.rs:7:5
  |
7 |     impl MyTrait for MyStruct {}
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: move this `impl` block outside the of the current function `foo` and up 2 bodies
  = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
  = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
  = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(non_local_definitions)]
  |         ^^^^^^^^^^^^^^^^^^^^^

解释

创建非本地定义违反了预期,并可能在工具中造成差异。应该避免这种情况。它可能在 2024 版本及更高版本中成为默认拒绝,请参阅跟踪问题 https://github.com/rust-lang/rust/issues/120363

如果 impl 定义嵌套在项目内部,并且类型和特性不在与 impl 块相同的嵌套级别,则它是非本地的。

所有嵌套主体(函数、枚举判别式、数组长度、常量)(除了顶层模块中的 const _: Ty = { ... },它仍然没有定论)都会被检查。

or-patterns-back-compat

lint or-patterns-back-compat 已重命名为 rust-2021-incompatible-or-patterns

redundant-lifetimes

redundant_lifetimes lint 检测由于等于另一个命名生命周期而冗余的生命周期参数。

示例

#[deny(redundant_lifetimes)]

// `'a = 'static`, so all usages of `'a` can be replaced with `'static`
pub fn bar<'a: 'static>() {}

// `'a = 'b`, so all usages of `'b` can be replaced with `'a`
pub fn bar<'a: 'b, 'b: 'a>() {}

这将产生

error: unnecessary lifetime parameter `'a`
 --> lint_example.rs:5:12
  |
5 | pub fn bar<'a: 'static>() {}
  |            ^^
  |
  = note: you can use the `'static` lifetime directly, in place of `'a`
note: the lint level is defined here
 --> lint_example.rs:2:8
  |
2 | #[deny(redundant_lifetimes)]
  |        ^^^^^^^^^^^^^^^^^^^

解释

未使用的生命周期参数可能表明错误或未完成的代码。考虑删除参数。

rust-2021-incompatible-closure-captures

rust_2021_incompatible_closure_captures lint 检测在 Rust 2021 中未完全捕获的变量,因此其字段的 Drop 顺序可能在 Rust 2018 和 2021 之间有所不同。

它还可以检测到当一个变量实现了像 Send 这样的 trait,但它的一个字段没有实现,并且该字段被闭包捕获并使用,假设该字段实现了与根变量相同的 trait。

drop 重新排序的示例

#![deny(rust_2021_incompatible_closure_captures)]
#![allow(unused)]

struct FancyInteger(i32);

impl Drop for FancyInteger {
    fn drop(&mut self) {
        println!("Just dropped {}", self.0);
    }
}

struct Point { x: FancyInteger, y: FancyInteger }

fn main() {
  let p = Point { x: FancyInteger(10), y: FancyInteger(20) };

  let c = || {
     let x = p.x;
  };

  c();

  // ... More code ...
}

这将产生

error: changes to closure capture in Rust 2021 will affect drop order
  --> lint_example.rs:17:11
   |
17 |   let c = || {
   |           ^^
18 |      let x = p.x;
   |              --- in Rust 2018, this closure captures all of `p`, but in Rust 2021, it will only capture `p.x`
...
24 | }
   | - in Rust 2018, `p` is dropped here, but in Rust 2021, only `p.x` will be dropped here as part of the closure
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(rust_2021_incompatible_closure_captures)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a dummy let to cause `p` to be fully captured
   |
17 ~   let c = || {
18 +      let _ = &p;
   |

解释

在上面的示例中,p.y 将在 f 结束时被丢弃,而不是在 Rust 2021 中与 c 一起丢弃。

自动 trait 的示例

#![deny(rust_2021_incompatible_closure_captures)]
use std::thread;

struct Pointer(*mut i32);
unsafe impl Send for Pointer {}

fn main() {
    let mut f = 10;
    let fptr = Pointer(&mut f as *mut i32);
    thread::spawn(move || unsafe {
        *fptr.0 = 20;
    });
}

这将产生

error: changes to closure capture in Rust 2021 will affect which traits the closure implements
  --> lint_example.rs:10:19
   |
10 |     thread::spawn(move || unsafe {
   |                   ^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send`
11 |         *fptr.0 = 20;
   |         ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(rust_2021_incompatible_closure_captures)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add a dummy let to cause `fptr` to be fully captured
   |
10 ~     thread::spawn(move || { let _ = &fptr; unsafe {
11 |         *fptr.0 = 20;
12 ~     } });
   |

解释

在上面的示例中,只有 fptr.0 在 Rust 2021 中被捕获。该字段的类型为 *mut i32,它没有实现 Send,这使得代码无效,因为该字段不能安全地在线程之间发送。

rust-2021-incompatible-or-patterns

rust_2021_incompatible_or_patterns lint 检测旧版本的或模式的使用。

示例

#![deny(rust_2021_incompatible_or_patterns)]

macro_rules! match_any {
    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
        match $expr {
            $(
                $( $pat => $expr_arm, )+
            )+
        }
    };
}

fn main() {
    let result: Result<i64, i32> = Err(42);
    let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
    assert_eq!(int, 42);
}

这将产生

error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
 --> lint_example.rs:4:26
  |
4 |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
  |                          ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param`
  |
  = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(rust_2021_incompatible_or_patterns)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

在 Rust 2021 中,pat 匹配器将匹配额外的模式,其中包括 | 字符。

rust-2021-prefixes-incompatible-syntax

rust_2021_prefixes_incompatible_syntax lint 检测将在 Rust 2021 中被解析为前缀的标识符。

示例

#![deny(rust_2021_prefixes_incompatible_syntax)]

macro_rules! m {
    (z $x:expr) => ();
}

m!(z"hey");

这将产生

error: prefix `z` is unknown
 --> lint_example.rs:8:4
  |
8 | m!(z"hey");
  |    ^ unknown prefix
  |
  = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/reserving-syntax.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(rust_2021_prefixes_incompatible_syntax)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
  |
8 | m!(z "hey");
  |     +

解释

在 Rust 2015 和 2018 中,z"hey" 是两个标记:标识符 z 后跟字符串字面量 "hey"。在 Rust 2021 中,z 被认为是 "hey" 的前缀。

此 lint 建议在 z"hey" 标记之间添加空格,以在 Rust 2021 中将它们分开。

rust-2021-prelude-collisions

rust_2021_prelude_collisions lint 检测使用与未来版本中添加到 prelude 的 trait 模糊的 trait 方法。

示例

#![deny(rust_2021_prelude_collisions)]

trait Foo {
    fn try_into(self) -> Result<String, !>;
}

impl Foo for &str {
    fn try_into(self) -> Result<String, !> {
        Ok(String::from(self))
    }
}

fn main() {
    let x: String = "3".try_into().unwrap();
    //                  ^^^^^^^^
    // This call to try_into matches both Foo::try_into and TryInto::try_into as
    // `TryInto` has been added to the Rust prelude in 2021 edition.
    println!("{x}");
}

这将产生

error: trait method `try_into` will become ambiguous in Rust 2021
  --> lint_example.rs:14:21
   |
14 |     let x: String = "3".try_into().unwrap();
   |                     ^^^^^^^^^^^^^^ help: disambiguate the associated function: `Foo::try_into(&*"3")`
   |
   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(rust_2021_prelude_collisions)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

在 Rust 2021 中,一个重要的引入是 prelude 更改,它将 TryFromTryIntoFromIterator 添加到标准库的 prelude 中。由于这会导致在通过点调用语法调用现有 try_into 方法或直接在类型上调用 try_from/from_iter 关联函数时,关于要调用哪个方法/函数的歧义。

single-use-lifetime

lint single-use-lifetime 已重命名为 single-use-lifetimes

single-use-lifetimes

single_use_lifetimes lint 检测仅使用一次的生命周期。

示例

#![deny(single_use_lifetimes)]

fn foo<'a>(x: &'a u32) {}

这将产生

error: lifetime parameter `'a` only used once
 --> lint_example.rs:4:8
  |
4 | fn foo<'a>(x: &'a u32) {}
  |        ^^      -- ...is used only here
  |        |
  |        this lifetime...
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(single_use_lifetimes)]
  |         ^^^^^^^^^^^^^^^^^^^^
help: elide the single-use lifetime
  |
4 - fn foo<'a>(x: &'a u32) {}
4 + fn foo(x: &u32) {}
  |

解释

在函数或 impl 中指定显式生命周期(如 'a)应该只用于将两个事物链接在一起。否则,你应该只使用 '_ 来表示生命周期没有与任何东西链接,或者如果可能的话,完全省略生命周期。

此 lint 默认情况下为“允许”,因为它是在 '_ 和省略的生命周期首次引入时引入的,并且此 lint 会过于嘈杂。此外,它还产生了一些已知的误报。有关历史背景,请参阅 RFC 2115,有关更多详细信息,请参阅 问题 #44752

trivial-casts

trivial_casts lint 检测可以替换为强制转换的琐碎转换,这可能需要一个临时变量。

示例

#![deny(trivial_casts)]
let x: &u32 = &42;
let y = x as *const u32;

这将产生

error: trivial cast: `&u32` as `*const u32`
 --> lint_example.rs:4:9
  |
4 | let y = x as *const u32;
  |         ^^^^^^^^^^^^^^^
  |
  = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(trivial_casts)]
  |         ^^^^^^^^^^^^^

解释

琐碎转换是转换 e as T,其中 e 的类型为 U,而 UT 的子类型。这种类型的转换通常是不必要的,因为它通常可以推断出来。

此 lint 默认情况下为“允许”,因为在某些情况下,例如使用 FFI 接口或复杂的类型别名,它会错误地触发,或者在难以清楚地表达意图的情况下。将来,它可能会成为警告,可能使用强制转换的显式语法来提供一种方便的方法来解决当前问题。有关历史背景,请参阅 RFC 401(强制转换)RFC 803(类型描述)RFC 3307(删除类型描述)

trivial-numeric-casts

trivial_numeric_casts lint 检测可以删除的类型的琐碎数字转换。

示例

#![deny(trivial_numeric_casts)]
let x = 42_i32 as i32;

这将产生

error: trivial numeric cast: `i32` as `i32`
 --> lint_example.rs:3:9
  |
3 | let x = 42_i32 as i32;
  |         ^^^^^^^^^^^^^
  |
  = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(trivial_numeric_casts)]
  |         ^^^^^^^^^^^^^^^^^^^^^

解释

琐碎数字转换是将数字类型转换为相同数字类型的转换。这种类型的转换通常是不必要的。

此 lint 默认情况下为“允许”,因为在某些情况下,例如使用 FFI 接口或复杂的类型别名,它会错误地触发,或者在难以清楚地表达意图的情况下。将来,它可能会成为警告,可能使用强制转换的显式语法来提供一种方便的方法来解决当前问题。有关历史背景,请参阅 RFC 401(强制转换)RFC 803(类型描述)RFC 3307(删除类型描述)

unit-bindings

unit_bindings lint 检测绑定无用的情况,因为它们具有单元类型 () 作为其推断类型。如果用户显式地用单元类型 () 注释 let 绑定,或者如果 let 绑定使用下划线通配符模式,即 let _ = expr,或者如果绑定是由宏扩展生成的,则会抑制该 lint。

示例

#![deny(unit_bindings)]

fn foo() {
    println!("do work");
}

pub fn main() {
    let x = foo(); // useless binding
}

这将产生

error: binding has unit type `()`
 --> lint_example.rs:8:5
  |
8 |     let x = foo(); // useless binding
  |     ^^^^-^^^^^^^^^
  |         |
  |         this pattern is inferred to be the unit type `()`
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unit_bindings)]
  |         ^^^^^^^^^^^^^

解释

使用单元类型 () 创建本地绑定不会做太多事情,并且可能是用户错误的标志,例如在这个示例中

fn main() {
    let mut x = [1, 2, 3];
    x[0] = 5;
    let y = x.sort(); // useless binding as `sort` returns `()` and not the sorted array.
    println!("{:?}", y); // prints "()"
}

unnameable-types

unnameable_types lint 检测可以获取该类型对象,但不能命名该类型本身的类型。

示例

#![allow(unused)]
#![deny(unnameable_types)]
mod m {
    pub struct S;
}

pub fn get_unnameable() -> m::S { m::S }
fn main() {}

这将产生

error: struct `S` is reachable but cannot be named
 --> lint_example.rs:4:5
  |
4 |     pub struct S;
  |     ^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
  |
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![deny(unnameable_types)]
  |         ^^^^^^^^^^^^^^^^

解释

通常期望的是,如果你可以获取类型 T 的对象,那么你也可以命名类型 T,此 lint 尝试强制执行此规则。建议的操作是正确地重新导出类型以使其可命名,或者记录用户不应该能够出于某种原因而命名它。

除了类型之外,此 lint 还适用于 trait,因为 trait 也可以通过签名泄漏,并且你可能会获取其 dyn Traitimpl Trait 类型的对象。

unreachable-pub

unreachable_pub lint 针对无法从其他 crate 访问的 pub 项目触发 - 这意味着既不能直接访问,也不能重新导出,也不能通过返回值类型等泄漏。

示例

#![deny(unreachable_pub)]
mod foo {
    pub mod bar {

    }
}

这将产生

error: unreachable `pub` item
 --> lint_example.rs:4:5
  |
4 |     pub mod bar {
  |     ---^^^^^^^^
  |     |
  |     help: consider restricting its visibility: `pub(crate)`
  |
  = help: or consider exporting it for use by other crates
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unreachable_pub)]
  |         ^^^^^^^^^^^^^^^

解释

pub 关键字既表达了对项目公开可用的意图,也向编译器发出信号,使其公开访问该项目。但是,只有当包含此项目的所有项目也公开可访问时,才能满足该意图。因此,此 lint 用于识别意图与现实不符的情况。

如果你希望该项目在 crate 中的其他地方可访问,但在外部不可访问,建议使用 pub(crate) 可见性。这更清楚地表达了该项目仅在其自身 crate 中可见的意图。

此 lint 默认情况下为“允许”,因为它会针对大量现有的 Rust 代码触发,并且有一些误报。最终,希望将其改为默认情况下为警告。

unsafe-code

unsafe_code lint 捕获 unsafe 代码和其他可能不安全的构造(如 no_mangleexport_namelink_section)的使用。

示例

#![deny(unsafe_code)]
fn main() {
    unsafe {

    }
}

#[no_mangle]
fn func_0() { }

#[export_name = "exported_symbol_name"]
pub fn name_in_rust() { }

#[no_mangle]
#[link_section = ".example_section"]
pub static VAR1: u32 = 1;

这将产生

error: usage of an `unsafe` block
 --> lint_example.rs:3:5
  |
3 | /     unsafe {
4 | |
5 | |     }
  | |_____^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unsafe_code)]
  |         ^^^^^^^^^^^


error: declaration of a `no_mangle` function
 --> lint_example.rs:8:1
  |
8 | #[no_mangle]
  | ^^^^^^^^^^^^
  |
  = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them


error: declaration of a function with `export_name`
  --> lint_example.rs:11:1
   |
11 | #[export_name = "exported_symbol_name"]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them


error: declaration of a `no_mangle` static
  --> lint_example.rs:14:1
   |
14 | #[no_mangle]
   | ^^^^^^^^^^^^
   |
   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them


error: declaration of a static with `link_section`
  --> lint_example.rs:15:1
   |
15 | #[link_section = ".example_section"]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them

解释

此 lint 的目的是限制 unsafe 块和其他构造(包括但不限于 no_manglelink_sectionexport_name 属性)的使用,错误使用这些构造会导致未定义的行为。

unsafe-op-in-unsafe-fn

unsafe_op_in_unsafe_fn lint 检测不安全函数中没有显式不安全块的不安全操作。

示例

#![deny(unsafe_op_in_unsafe_fn)]

unsafe fn foo() {}

unsafe fn bar() {
    foo();
}

fn main() {}

这将产生

error: call to unsafe function `foo` is unsafe and requires unsafe block (error E0133)
 --> lint_example.rs:6:5
  |
6 |     foo();
  |     ^^^^^ call to unsafe function
  |
  = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
  = note: consult the function's documentation for information on how to avoid undefined behavior
note: an unsafe function restricts its caller, but its body is safe by default
 --> lint_example.rs:5:1
  |
5 | unsafe fn bar() {
  | ^^^^^^^^^^^^^^^
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unsafe_op_in_unsafe_fn)]
  |         ^^^^^^^^^^^^^^^^^^^^^^

解释

目前,unsafe fn 允许其主体内的任何 不安全 操作。但是,这会增加需要仔细检查以确保其行为正确的代码的表面积。 unsafe 提供了一种方便的方法,可以清楚地表明代码的哪些部分正在执行不安全操作。将来,希望将其更改为,在没有 unsafe 块的情况下,不能在 unsafe fn 中执行不安全操作。

对此的修复是将不安全代码包装在 unsafe 块中。

此 lint 默认情况下在 2021 年之前的版本中为“允许”,从 2024 年开始,默认情况下为“警告”;进一步提高严重性的计划仍在考虑中。有关更多详细信息,请参阅 RFC #2585问题 #71668

unstable-features

unstable_features lint 检测 #![feature] 的使用。

示例

#![deny(unstable_features)]
#![feature(test)]

这将产生

error: use of an unstable feature
 --> lint_example.rs:2:12
  |
2 | #![feature(test)]
  |            ^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unstable_features)]
  |         ^^^^^^^^^^^^^^^^^

解释

在更大的基于 nightly 的项目中,

  • 由多个 crate 组成,其中一部分 crate 必须在稳定版本上编译,无论是有条件地还是取决于 cfg 标志,例如允许稳定用户依赖它们,
  • 不要使用 nightly 来进行实验性功能,而是使用,例如,仅使用不稳定选项,

此 lint 可能有助于强制执行这些类型的策略。

unused-crate-dependencies

unused_crate_dependencies lint 检测从未使用的 crate 依赖项。

示例

#![deny(unused_crate_dependencies)]

这将产生

error: external crate `regex` unused in `lint_example`: remove the dependency or add `use regex as _;`
  |
note: the lint level is defined here
 --> src/lib.rs:1:9
  |
1 | #![deny(unused_crate_dependencies)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^

解释

删除使用依赖项的代码后,通常还需要从构建配置中删除依赖项。但是,有时可能会遗漏此步骤,这会导致浪费时间构建不再使用的依赖项。可以启用此 lint 来检测从未使用的依赖项(更具体地说,任何使用 --extern 命令行标志传递的依赖项,从未通过 useextern crate 或任何 路径 引用)。

此 lint 默认情况下为“允许”,因为它可能会根据构建系统的配置提供误报。例如,当使用 Cargo 时,“包”由多个 crate 组成(例如库和二进制文件),但依赖项是为整个包定义的。如果有一个依赖项仅在二进制文件中使用,而不是在库中使用,那么 lint 将在库中错误地发出。

unused-extern-crates

unused_extern_crates lint 防止从未使用的 extern crate 项目。

示例

#![deny(unused_extern_crates)]
#![deny(warnings)]
extern crate proc_macro;

这将产生

error: unused extern crate
 --> lint_example.rs:4:1
  |
4 | extern crate proc_macro;
  | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unused_extern_crates)]
  |         ^^^^^^^^^^^^^^^^^^^^

解释

extern crate 项目如果未使用,则没有任何效果,应该将其删除。请注意,在某些情况下,指定 extern crate 是为了确保链接给定 crate 的副作用,即使它没有被直接引用。可以通过将 crate 关联到下划线来消除 lint,例如 extern crate foo as _。还要注意,在 2018 版本 中,使用 extern crate 已经不再是惯例,因为 extern crate 现在会自动添加到作用域中。

此 lint 默认情况下为“允许”,因为它可能会很吵,并且会产生误报。如果要从项目中删除依赖项,建议将其从构建配置(例如 Cargo.toml)中删除,以确保不会留下过时的构建条目。

unused-import-braces

unused_import_braces lint 捕获导入项周围不必要的括号。

示例

#![deny(unused_import_braces)]
use test::{A};

pub mod test {
    pub struct A;
}
fn main() {}

这将产生

error: braces around A is unnecessary
 --> lint_example.rs:2:1
  |
2 | use test::{A};
  | ^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unused_import_braces)]
  |         ^^^^^^^^^^^^^^^^^^^^

解释

如果只有一个项目,则删除括号(例如 use test::A;)。

此 lint 默认情况下为“允许”,因为它只在强制执行一种风格选择。

unused-lifetimes

unused_lifetimes lint 检测从未使用过的生命周期参数。

示例

#[deny(unused_lifetimes)]

pub fn foo<'a>() {}

这将产生

error: lifetime parameter `'a` never used
 --> lint_example.rs:4:12
  |
4 | pub fn foo<'a>() {}
  |           -^^- help: elide the unused lifetime
  |
note: the lint level is defined here
 --> lint_example.rs:2:8
  |
2 | #[deny(unused_lifetimes)]
  |        ^^^^^^^^^^^^^^^^

解释

未使用的生命周期参数可能表明错误或未完成的代码。考虑删除参数。

unused-macro-rules

unused_macro_rules lint 检测从未使用过的宏规则。

请注意,该 lint 与 unused_macros lint 不同,unused_macros lint 会在整个宏从未被调用时触发,而此 lint 会在宏的单个未使用规则(该宏在其他情况下被使用)时触发。unused_macro_rules 仅在 unused_macros 不会触发时才会触发。

示例

#[warn(unused_macro_rules)]
macro_rules! unused_empty {
    (hello) => { println!("Hello, world!") }; // This rule is unused
    () => { println!("empty") }; // This rule is used
}

fn main() {
    unused_empty!(hello);
}

这将产生

warning: 2nd rule of macro `unused_empty` is never used
 --> lint_example.rs:4:5
  |
4 |     () => { println!("empty") }; // This rule is used
  |     ^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:8
  |
1 | #[warn(unused_macro_rules)]
  |        ^^^^^^^^^^^^^^^^^^

解释

未使用的宏规则可能表明存在错误或未完成的代码。此外,它们会减慢编译速度。目前,在单个规则级别上不支持消除警告,因此你必须对整个宏定义添加允许。

如果你打算导出宏以使其在 crate 外部可用,请使用 macro_export 属性

unused-qualifications

unused_qualifications lint 检测不必要的限定名称。

示例

#![deny(unused_qualifications)]
mod foo {
    pub fn bar() {}
}

fn main() {
    use foo::bar;
    foo::bar();
    bar();
}

这将产生

error: unnecessary qualification
 --> lint_example.rs:8:5
  |
8 |     foo::bar();
  |     ^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unused_qualifications)]
  |         ^^^^^^^^^^^^^^^^^^^^^
help: remove the unnecessary path segments
  |
8 -     foo::bar();
8 +     bar();
  |

解释

如果来自另一个模块的项目已经被引入作用域,那么在这种情况下就没有必要限定它。你可以直接调用 bar(),而无需 foo::

此 lint 默认情况下为“允许”,因为它有点吹毛求疵,并且没有表明实际问题,而只是一种风格选择,并且在重构或移动代码时可能会很吵。

unused-results

unused_results lint 检查语句中表达式未使用的结果。

示例

#![deny(unused_results)]
fn foo<T>() -> T { panic!() }

fn main() {
    foo::<usize>();
}

这将产生

error: unused result of type `usize`
 --> lint_example.rs:5:5
  |
5 |     foo::<usize>();
  |     ^^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(unused_results)]
  |         ^^^^^^^^^^^^^^

解释

忽略函数的返回值可能表明存在错误。在几乎可以确定应该使用结果的情况下,建议使用 must_use 属性 对函数进行注释。未使用此类返回值将触发 unused_must_use 警告,该警告默认情况下处于启用状态。unused_results 警告与之类似,但会针对所有返回值触发。

此警告默认情况下处于“允许”状态,因为它可能过于频繁,并且可能不是实际问题。例如,调用 VecHashMapremove 方法会返回先前值,您可能并不关心该值。使用此警告将需要显式忽略或丢弃此类值。

variant-size-differences

variant_size_differences 警告检测具有较大变体大小差异的枚举。

示例

#![deny(variant_size_differences)]
enum En {
    V0(u8),
    VBig([u8; 1024]),
}

这将产生

error: enum variant is more than three times larger (1024 bytes) than the next largest
 --> lint_example.rs:5:5
  |
5 |     VBig([u8; 1024]),
  |     ^^^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(variant_size_differences)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^

解释

向枚举添加一个比其他变体大得多的变体可能是一个错误,这会导致所有变体所需的总大小膨胀。这会影响性能和内存使用。如果一个变体比第二大变体大 3 倍以上,就会触发此警告。

考虑将大型变体的内容放置在堆上(例如,通过 Box)以减小枚举本身的总大小。

此警告默认情况下处于“允许”状态,因为它可能过于频繁,并且可能不是实际问题。有关此方面的决策应以分析和基准测试为指导。