默认允许的 Lint

这些 lint 默认都设置为 'allow' 级别。因此,除非您使用 flag 或 attribute 将它们设置为更高的 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 版本中是完全有效的。cargo fix 工具与 --edition flag 一起使用会将此 lint 切换为 “warn”,并自动应用编译器建议的修复。这提供了一种完全自动化的方式来更新旧代码以适应 2018 版本。

ambiguous-negative-literals

ambiguous_negative_literals lint 检查负字面量和不属于字面量的否定之间容易混淆的情况。

示例

#![deny(ambiguous_negative_literals)]
#![allow(unused)]
-1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1

这将产生

error: `-` has lower precedence than method calls, which might be unexpected
 --> lint_example.rs:4:1
  |
4 | -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
  | ^^^^^^^^^^^
  |
  = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(ambiguous_negative_literals)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add parentheses around the `-` and the literal to call the method on a negative literal
  |
4 | (-1i32).abs(); // equals -1, while `(-1i32).abs()` equals 1
  | +     +
help: add parentheses around the literal and the method call to keep the current behavior
  |
4 | -(1i32.abs()); // equals -1, while `(-1i32).abs()` equals 1
  |  +          +

解释

方法调用优先于一元优先级。显式设置优先级可以使代码更清晰,并避免潜在的错误。

async-idents

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

closure-returning-async-block

closure_returning_async_block lint 检测用户编写返回 async block 的闭包的情况。

示例

#![warn(closure_returning_async_block)]
let c = |x: &str| async {};

这将产生

warning: closure returning async block can be made into an async closure
 --> lint_example.rs:3:9
  |
3 | let c = |x: &str| async {};
  |         ^^^^^^^^^ ----- this async block can be removed, and the closure can be turned into an async closure
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(closure_returning_async_block)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: turn this into an async closure
  |
3 - let c = |x: &str| async {};
3 + let c = async |x: &str| {};
  |

解释

使用 async 闭包比返回 async block 的闭包更可取,因为 async 闭包对其捕获的使用方式限制较少。

例如,以下代码不适用于返回 async block 的闭包

async fn callback(x: &str) {}

let captured_str = String::new();
let c = move || async {
    callback(&captured_str).await;
};

但它适用于 async 闭包

async fn callback(x: &str) {}

let captured_str = String::new();
let c = async move || {
    callback(&captured_str).await;
};

deprecated-safe-2024

deprecated_safe_2024 lint 检测被用作 safe 函数的 unsafe 函数。

示例

#![deny(deprecated_safe)]
// edition 2021
use std::env;
fn enable_backtrace() {
    env::set_var("RUST_BACKTRACE", "1");
}

这将产生

error: call to deprecated safe function `std::env::set_var` is unsafe and requires unsafe block
 --> lint_example.rs:6:5
  |
6 |     env::set_var("RUST_BACKTRACE", "1");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
  |
  = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/newly-unsafe-functions.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(deprecated_safe)]
  |         ^^^^^^^^^^^^^^^
  = note: `#[deny(deprecated_safe_2024)]` implied by `#[deny(deprecated_safe)]`
help: you can wrap the call in an `unsafe` block if you can guarantee that the environment access only happens in single-threaded code
  |
6 +     // TODO: Audit that the environment access only happens in single-threaded code.
7 ~     unsafe { env::set_var("RUST_BACKTRACE", "1") };
  |

解释

Rust 版本 允许语言在不破坏向后兼容性的情况下发展。此 lint 捕获在 Rust 2024 之前版本中声明为 safe(非 unsafe)的 unsafe 函数的代码。如果您在不更新代码的情况下将编译器切换到 Rust 2024,那么如果您正在使用之前标记为 safe 的函数,则编译将失败。

您可以审核代码以查看它是否满足 unsafe 代码的先决条件,如果满足,您可以将其包装在 unsafe block 中。如果您无法满足先决条件,您可能需要切换到其他方式来完成您想要实现的目标。

此 lint 可以自动将调用包装在 unsafe block 中,但这显然无法验证 unsafe 函数的先决条件是否得到满足,因此这仍然取决于用户。

此 lint 当前默认设置为 “allow”,但这在未来可能会改变。

disjoint-capture-migration

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

edition-2024-expr-fragment-specifier

edition_2024_expr_fragment_specifier lint 检测在迁移到 2024 版本期间在宏中使用 expr 片段的情况。

expr 片段说明符将在 2024 版本中接受更多表达式。要保持 2021 版本及更早版本的行为,请使用 expr_2021 片段说明符。

示例

#![deny(edition_2024_expr_fragment_specifier)]
macro_rules! m {
  ($e:expr) => {
      $e
  }
}

fn main() {
   m!(1);
}

这将产生

error: the `expr` fragment specifier will accept more expressions in the 2024 edition
 --> lint_example.rs:3:7
  |
3 |   ($e:expr) => {
  |       ^^^^
  |
  = warning: this changes meaning in Rust 2024
  = note: for more information, see Migration Guide <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/macro-fragment-specifiers.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(edition_2024_expr_fragment_specifier)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to keep the existing behavior, use the `expr_2021` fragment specifier
  |
3 |   ($e:expr_2021) => {
  |       ~~~~~~~~~

解释

Rust 版本 允许语言在不破坏向后兼容性的情况下发展。此 lint 捕获使用了在 2024 版本中含义发生变化的 宏匹配器片段说明符 的代码。如果您在不更新代码的情况下切换到新版本,您的宏可能会表现不同。

在 2024 版本中,expr 片段说明符 expr 也将匹配 const { ... } block。这意味着如果一个宏有一个模式匹配 $e:expr,另一个模式匹配 const { $e: expr },例如,在 2024 版本下,第一个模式将匹配,而在 2021 及更早版本中,第二个模式将匹配。要保持旧行为,请使用 expr_2021 片段说明符。

此 lint 检测行为可能因 expr 片段说明符的含义更改而发生变化的宏。默认情况下,它被设置为 “allow”,因为该代码在旧版本中是完全有效的。cargo fix 工具与 --edition flag 一起使用会将此 lint 切换为 “warn”,并自动应用编译器建议的修复。这提供了一种完全自动化的方式来更新旧代码以适应新版本。

cargo fix --edition 与此 lint 一起使用将确保您的代码保留相同的行为。这可能不是期望的行为,因为宏作者通常希望他们的宏使用最新的语法来匹配表达式。请务必仔细审查由此 lint 引入的更改,以确保宏实现所需的行为。

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 检测可以推断出的不必要的生命周期 bound。

示例

#![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。历史上,这需要编写显式的生命周期 bound 来指示此要求。然而,这可能过于显式,导致混乱和不必要的复杂性。语言已更改为在未指定 bound 的情况下自动推断 bound。具体来说,如果 struct 直接或间接地包含对具有生命周期 'xT 的引用,那么它将推断出 T: 'x 是一项要求。

此 lint 默认设置为 “allow”,因为它对于已经具有这些要求的现有代码来说可能很嘈杂。这是一个风格选择,因为显式声明 bound 仍然是有效的。它也存在一些可能引起混淆的误报。

有关更多详细信息,请参阅 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 转换。

示例

#![warn(fuzzy_provenance_casts)]

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

这将产生

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

解释

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

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

if-let-rescope

if_let_rescope lint 检测在 if let 右侧生成具有重要 drop 的临时值的情况,并建议在可能的情况下重写为 match

示例

#![warn(if_let_rescope)]
#![allow(unused_variables)]

struct Droppy;
impl Drop for Droppy {
    fn drop(&mut self) {
        // Custom destructor, including this `drop` implementation, is considered
        // significant.
        // Rust does not check whether this destructor emits side-effects that can
        // lead to observable change in program semantics, when the drop order changes.
        // Rust biases to be on the safe side, so that you can apply discretion whether
        // this change indeed breaches any contract or specification that your code needs
        // to honour.
        println!("dropped");
    }
}
impl Droppy {
    fn get(&self) -> Option<u8> {
        None
    }
}

fn main() {
    if let Some(value) = Droppy.get() {
        // do something
    } else {
        // do something else
    }
}

这将产生

warning: `if let` assigns a shorter lifetime since Edition 2024
  --> lint_example.rs:24:8
   |
24 |     if let Some(value) = Droppy.get() {
   |        ^^^^^^^^^^^^^^^^^^------^^^^^^
   |                          |
   |                          this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
   |
   = warning: this changes meaning in Rust 2024
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
help: the value is now dropped here in Edition 2024
  --> lint_example.rs:26:5
   |
26 |     } else {
   |     ^
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![warn(if_let_rescope)]
   |         ^^^^^^^^^^^^^^
help: a `match` with a single arm can preserve the drop order up to Edition 2021
   |
24 ~     match Droppy.get() { Some(value) => {
25 |         // do something
26 ~     } _ => {
27 |         // do something else
28 ~     }}
   |

解释

在 2024 版本中,在评估 if let 时生成的临时值将在 else block 之前被 drop。此 lint 捕获了由于对重要的 Drop::drop 析构函数的调用顺序发生更改而可能导致运行时行为发生变化的情况。

重要的 Drop::drop 析构函数此处指的是对类型显式、任意实现的 Drop trait,例外情况包括 VecBoxRcBTreeMapHashMap,这些类型由编译器以其他方式标记,只要泛型类型没有以递归方式进行重要的析构函数。换句话说,当一个类型具有 Drop 实现或者其析构函数在类型上调用重要的析构函数时,该类型就具有重要的 drop 析构函数。由于我们无法仅通过检查重要析构函数的存在来完全推断更改,因此此 lint 仍然只是一个建议,并且默认设置为 allow

在可能的情况下,此 lint 会提出重写为等效的 match 表达式,该表达式观察到此类析构函数的相同调用顺序。作者可以自行决定是否应接受重写建议,或者拒绝继续使用 if let 表达式。

impl-trait-overcaptures

impl_trait_overcaptures lint 警告在 2024 版本中生命周期捕获行为将有所不同的情况。

在 2024 版本中,impl Trait 将捕获作用域内的所有生命周期,而不仅仅是类型 bound 中提到的生命周期。通常这些集合是相等的,但如果不是,则意味着 impl Trait 可能会导致错误的借用检查器错误。

示例

#![deny(impl_trait_overcaptures)]
use std::fmt::Display;
let mut x = vec![];
x.push(1);

fn test(x: &Vec<i32>) -> impl Display {
    x[0]
}

let element = test(&x);
x.push(2);
println!("{element}");

这将产生

error: `impl std::fmt::Display` will capture more lifetimes than possibly intended in edition 2024
 --> lint_example.rs:7:26
  |
7 | fn test(x: &Vec<i32>) -> impl Display {
  |                          ^^^^^^^^^^^^
  |
  = warning: this changes meaning in Rust 2024
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html>
note: specifically, this lifetime is in scope but not mentioned in the type's bounds
 --> lint_example.rs:7:12
  |
7 | fn test(x: &Vec<i32>) -> impl Display {
  |            ^
  = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(impl_trait_overcaptures)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^
help: use the precise capturing `use<...>` syntax to make the captures explicit
  |
7 | fn test(x: &Vec<i32>) -> impl Display + use<> {
  |                                       +++++++

解释

在版本 < 2024 中,返回的 impl Display 不会捕获来自 &Vec<i32> 的生命周期,因此当 impl Display 处于活动状态时,可以可变地借用 vector。

要解决此问题,我们可以使用 impl Display + use<> 显式声明 impl Display 不捕获任何生命周期。

impl-trait-redundant-captures

impl_trait_redundant_captures lint 警告不需要使用精确捕获 use<...> 语法的情况。

在 2024 版本中,impl Trait 将捕获作用域内的所有生命周期。如果使用了精确捕获 use<...> 语法,并且捕获的参数集等于作用域内的参数集,则该语法是冗余的,可以删除。

示例

#![feature(lifetime_capture_rules_2024)]
#![deny(impl_trait_redundant_captures)]
fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }

这将产生

error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
 --> lint_example.rs:4:28
  |
4 | fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
  |                            ^^^^^^^^^^^^^-------
  |                                         |
  |                                         help: remove the `use<...>` syntax
  |
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![deny(impl_trait_redundant_captures)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

要修复此问题,请删除 use<'a>,因为生命周期已经在作用域内被捕获。

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 自动解决问题。默认情况下,它被设置为 “allow”,因为该代码在旧版本中是完全有效的。cargo fix 工具与 --edition flag 一起使用会将此 lint 切换为 “warn”,并自动应用编译器建议的修复(即使用原始标识符)。这提供了一种完全自动化的方式来更新旧代码以适应新版本。

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 <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/gen-keyword.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(keyword_idents_2024)]
  |         ^^^^^^^^^^^^^^^^^^^

解释

Rust 版本 允许语言在不破坏向后兼容性的情况下发展。此 lint 捕获将添加到语言中的新关键字用作标识符(例如变量名、函数名等)的代码。如果您在不更新代码的情况下将编译器切换到新版本,那么如果您使用新关键字作为标识符,则编译将失败。

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

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

let-underscore-drop

let_underscore_drop lint 检查不将具有非平凡 Drop 实现的表达式绑定到任何内容的语句,导致表达式立即被 drop 而不是在作用域结束时被 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 has a destructor
  --> 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);
   |     ~~~~~          +

解释

将表达式赋值给下划线的语句会导致表达式立即 drop,而不是将表达式的生命周期延长到作用域结束。这通常是意外的,特别是对于像 MutexGuard 这样的类型,这些类型通常用于在整个作用域内锁定互斥锁。

如果您想将表达式的生命周期延长到作用域结束,请将以下划线为前缀的名称(例如 _foo)分配给表达式。如果您确实想立即 drop 表达式,那么在表达式上调用 std::mem::drop 更清晰,并且有助于传达意图。

lossy-provenance-casts

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

示例

#![warn(lossy_provenance_casts)]

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

这将产生

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

解释

此 lint 是严格来源努力的一部分,请参阅 issue #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 attribute 的使用。

示例

#![deny(macro_use_extern_crate)]

#[macro_use]
extern crate serde_json;

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

这将产生

error: applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
 --> src/main.rs:3:1
  |
3 | #[macro_use]
  | ^^^^^^^^^^^^
  |
  = help: remove it and import macros at use sites with a `use` item instead
note: the lint level is defined here
 --> src/main.rs:1:9
  |
1 | #![deny(macro_use_extern_crate)]
  |         ^^^^^^^^^^^^^^^^^^^^^^

解释

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

此 lint 默认设置为 “allow”,因为这是一个尚未确定的风格选择,有关更多信息,请参阅 issue #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 默认设置为 “allow”,因为它可能存在误报和其他问题。有关更多详细信息,请参阅 issue #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() {}
  | ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(missing_abi)]
  |         ^^^^^^^^^^^

解释

由于历史原因,Rust 隐式选择 C 作为 extern 声明的默认 ABI。其他 ABI(如 C-unwindsystem)自那时以来已被添加,特别是随着它们的添加,容易看到 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 trait 来显式选择加入。作为此更改的一部分,添加了一个 lint,以在可复制类型未标记为 Copy 时发出警报。

此 lint 默认设置为 “allow”,因为此代码并不坏;编写像这样的 newtype 以专门使 Copy 类型不再是 Copy 是很常见的。Copy 类型可能会导致大型数据的不必要副本,从而影响性能。

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)] attribute 将自动生成典型的实现,或者可以通过手动实现 Debug trait 来添加自定义实现。

此 lint 默认设置为 “allow”,因为向所有类型添加 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 默认设置为 “allow”,因为它可能很嘈杂,并且并非所有项目都希望强制所有内容都必须记录在案。

missing-unsafe-on-extern

missing_unsafe_on_extern lint 检测外部声明中缺少 unsafe 关键字。

示例

#![warn(missing_unsafe_on_extern)]
#![allow(dead_code)]

extern "C" {
    fn foo(_: i32);
}

fn main() {}

这将产生

warning: extern blocks should be unsafe
 --> lint_example.rs:4:1
  |
4 |   extern "C" {
  |   ^
  |   |
  |  _help: needs `unsafe` before the extern keyword: `unsafe`
  | |
5 | |     fn foo(_: i32);
6 | | }
  | |_^
  |
  = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/unsafe-extern.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(missing_unsafe_on_extern)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^

解释

声明外部项,即使从未使用过它们,也可能导致未定义行为。我们应该将所有未定义行为的来源都视为不安全的。

这是一个 未来不兼容的 lint,以便将来过渡到硬错误。

multiple-supertrait-upcastable

multiple_supertrait_upcastable lint 检测 dyn 兼容 trait 何时具有多个 supertrait。

示例

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

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

这将产生

warning: `C` is dyn-compatible 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)]
  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

为了支持具有多个 supertrait 的 upcasting,我们需要存储多个 vtable,即使没有代码实际使用 upcasting,这也会导致额外的空间开销。此 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] attribute 的值。“挂起” 点通常是 async 函数中的 .await

此 attribute 可用于标记在挂起期间语义上不正确的值(例如某些类型的计时器)、具有异步替代项的值以及通常会导致 async fn 返回的 future 的 Send-ness 出现问题的值(例如 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 切换为 “forbid”(例如,为了方便协作或出于安全原因)。有关更多详细信息,请参阅 RFC 2457

non-exhaustive-omitted-patterns

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

#[non_exhaustive] 注解强制匹配使用通配符,因此 exhaustiveness 检查不能用于确保所有字段/变体都被显式匹配。为了弥补这一点,当 match 提及 #[non_exhaustive] struct 或 enum 的某些但不是全部字段/变体时,此默认允许的 lint 会警告用户。

示例

// 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] struct 或 enum 添加字段或变体)破坏您的 crate。这违反了预期的 semver 行为。

解释

使用 #[non_exhaustive] 标记的 Struct 和 enum 强制用户在模式匹配时添加(可能冗余的)通配符,以允许将来添加字段或变体。当通配符碰巧实际捕获了一些字段/变体时,non_exhaustive_omitted_patterns lint 会检测到这种情况。换句话说,当没有通配符的 match 将不是 exhaustive 时。这让用户了解是否添加了新字段/变体。

or-patterns-back-compat

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

redundant-imports

redundant_imports lint 检测由于已被导入而变得冗余的 import;通过之前的 import 或存在于 prelude 中。

示例

#![deny(redundant_imports)]
use std::option::Option::None;
fn foo() -> Option<i32> { None }

这将产生

error: the item `None` is imported redundantly
   --> lint_example.rs:3:5
    |
3   | use std::option::Option::None;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
   ::: /checkout/library/std/src/prelude/mod.rs:166:13
    |
166 |     pub use core::prelude::rust_2021::*;
    |             ------------------------ the item `None` is already defined here
    |
note: the lint level is defined here
   --> lint_example.rs:1:9
    |
1   | #![deny(redundant_imports)]
    |         ^^^^^^^^^^^^^^^^^

解释

冗余的 import 是不必要的,可以删除以简化代码。如果您打算重新导出该项以使其在模块外部可用,请添加可见性修饰符,如 pub

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 结束时被 drop,而不是在 Rust 2021 中与 c 一起被 drop。

Auto-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 ~     } });
   |

解释

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

rust-2021-incompatible-or-patterns

rust_2021_incompatible_or_patterns lint 检测旧版本的 or-patterns 的使用。

示例

#![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" 是两个 token:标识符 z 后跟字符串字面量 "hey"。在 Rust 2021 中,z 被视为 "hey" 的前缀。

此 lint 建议在 z"hey" token 之间添加空格,以使它们在 Rust 2021 中保持分隔。

rust-2021-prelude-collisions

rust_2021_prelude_collisions lint 检测 trait 方法的使用,这些方法与未来版本中添加到 prelude 中的 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 关联函数时,这会导致调用哪个方法/函数的歧义。

rust-2024-guarded-string-incompatible-syntax

rust_2024_guarded_string_incompatible_syntax lint 检测将在 Rust 2024 中解析为受保护字符串字面量一部分的 # token。

示例

#![deny(rust_2024_guarded_string_incompatible_syntax)]

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

m!(#"hey"#);
m!(#"hello");

这将产生

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


error: will be parsed as a guarded string in Rust 2024
  --> lint_example.rs:10:4
   |
10 | m!(#"hello");
   |    ^^^^^^^^
   |
   = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/reserved-syntax.html>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
   |
10 | m!(# "hello");
   |     +

解释

在 Rust 2024 之前,#"hey"# 是三个 token:第一个 # 后跟字符串字面量 "hey",然后是最后一个 #。在 Rust 2024 中,整个序列被视为单个 token。

此 lint 建议在开头的 # 和字符串之间添加空格,以使它们在 Rust 2024 中保持分隔。

rust-2024-incompatible-pat

rust_2024_incompatible_pat lint 检测在 Rust 2024 版本中含义将发生变化的模式。

示例

#![warn(rust_2024_incompatible_pat)]

if let Some(&a) = &Some(&0u8) {
    let _: u8 = a;
}
if let Some(mut _a) = &mut Some(0u8) {
    _a = 7u8;
}

这将产生

warning: reference patterns may only be written when the default binding mode is `move` in Rust 2024
 --> lint_example.rs:4:13
  |
4 | if let Some(&a) = &Some(&0u8) {
  |             ^ reference pattern not allowed under `ref` default binding mode
  |
  = warning: this changes meaning in Rust 2024
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: matching on a reference type with a non-reference pattern changes the default binding mode
 --> lint_example.rs:4:8
  |
4 | if let Some(&a) = &Some(&0u8) {
  |        ^^^^^^^^ this matches on type `&_`
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(rust_2024_incompatible_pat)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: make the implied reference pattern explicit
  |
4 | if let &Some(&a) = &Some(&0u8) {
  |        +


warning: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
 --> lint_example.rs:7:13
  |
7 | if let Some(mut _a) = &mut Some(0u8) {
  |             ^^^ binding modifier not allowed under `ref mut` default binding mode
  |
  = warning: this changes meaning in Rust 2024
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: matching on a reference type with a non-reference pattern changes the default binding mode
 --> lint_example.rs:7:8
  |
7 | if let Some(mut _a) = &mut Some(0u8) {
  |        ^^^^^^^^^^^^ this matches on type `&mut _`
help: make the implied reference pattern explicit
  |
7 | if let &mut Some(mut _a) = &mut Some(0u8) {
  |        ++++

解释

在 Rust 2024 及更高版本中,mut 关键字不会重置模式绑定模式,&&mut 模式也不会。此 lint 将建议在所有版本中都具有相同含义的代码。

rust-2024-prelude-collisions

rust_2024_prelude_collisions lint 检测 trait 方法的使用,这些方法与未来版本中添加到 prelude 中的 trait 存在歧义。

示例

#![deny(rust_2024_prelude_collisions)]
trait Meow {
    fn poll(&self) {}
}
impl<T> Meow for T {}

fn main() {
    core::pin::pin!(async {}).poll();
    //                        ^^^^^^
    // This call to try_into matches both Future::poll and Meow::poll as
    // `Future` has been added to the Rust prelude in 2024 edition.
}

这将产生

error: trait method `poll` will become ambiguous in Rust 2024
 --> lint_example.rs:8:5
  |
8 |     core::pin::pin!(async {}).poll();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}))`
  |
  = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/prelude.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(rust_2024_prelude_collisions)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

Rust 2024 向标准库的 prelude 引入了两个新添加项:FutureIntoFuture。当通过点调用语法调用现有的 poll/into_future 方法或直接在类型上调用 poll/into_future 关联函数时,这会导致调用哪个方法/函数的歧义。

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 默认设置为 “allow”,因为它是在 '_ 和省略生命周期首次引入时引入的,并且此 lint 会过于嘈杂。此外,它还会产生一些已知的误报。有关历史背景,请参阅 RFC 2115,有关更多详细信息,请参阅 issue #44752

tail-expr-drop-order

tail_expr_drop_order lint 查找在尾表达式位置生成的、运行自定义 Drop 析构器的值。在 Edition 2024 中,它们中的一些可能会比在 Edition 2021 及更早版本中更早地被 drop。此 lint 检测到这些情况,并为您提供有关这些值及其自定义析构器实现的信息。您需要自行斟酌使用这些信息。

示例

#![warn(tail_expr_drop_order)]
struct Droppy(i32);
impl Droppy {
    fn get(&self) -> i32 {
        self.0
    }
}
impl Drop for Droppy {
    fn drop(&mut self) {
        // This is a custom destructor and it induces side-effects that is observable
        // especially when the drop order at a tail expression changes.
        println!("loud drop {}", self.0);
    }
}
fn edition_2021() -> i32 {
    let another_droppy = Droppy(0);
    Droppy(1).get()
}
fn main() {
    edition_2021();
}

这将产生

warning: relative drop order changing in Rust 2024
  --> lint_example.rs:17:5
   |
16 |     let another_droppy = Droppy(0);
   |         --------------
   |         |
   |         `another_droppy` calls a custom destructor
   |         `another_droppy` will be dropped later as of Edition 2024
17 |     Droppy(1).get()
   |     ^^^^^^^^^
   |     |
   |     this value will be stored in a temporary; let us call it `#1`
   |     up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024
18 | }
   | - now the temporary value is dropped here, before the local variables in the block or statement
   |
   = warning: this changes meaning in Rust 2024
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
note: `#1` invokes this custom destructor
  --> lint_example.rs:8:1
   |
8  | / impl Drop for Droppy {
9  | |     fn drop(&mut self) {
...  |
14 | | }
   | |_^
note: `another_droppy` invokes this custom destructor
  --> lint_example.rs:8:1
   |
8  | / impl Drop for Droppy {
9  | |     fn drop(&mut self) {
...  |
14 | | }
   | |_^
   = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![warn(tail_expr_drop_order)]
   |         ^^^^^^^^^^^^^^^^^^^^

解释

在代码块或函数体的尾表达式中,具有重要 Drop 实现的类型的值在 Edition 2024 之前具有不明确的 drop 顺序,因此它们仅在 drop 局部变量之后才被 drop。Edition 2024 引入了新的规则来规定它们的 drop 顺序,以便它们在 drop 局部变量之前首先被 drop。

这里重要的 Drop::drop 析构器指的是类型上 Drop trait 的显式、任意实现,例外情况包括 VecBoxRcBTreeMapHashMap,只要泛型类型没有递归的重要析构器,编译器就会以其他方式标记它们。换句话说,当一个类型具有 Drop 实现或其析构器调用类型上的重要析构器时,该类型就具有重要的 drop 析构器。由于我们无法仅通过检查重要析构器的存在来完全推断更改,因此此 lint 仍然只是一种建议,并且默认设置为 allow

此 lint 仅指出 Droppy 的问题,在 Edition 2024 中,它将在 another_droppy 之前被 drop。此 lint 不会提出任何修复建议。但是,最可能的修复方法是将 Droppy 提升到它自己的局部变量绑定中。

struct Droppy(i32);
impl Droppy {
    fn get(&self) -> i32 {
        self.0
    }
}
fn edition_2024() -> i32 {
    let value = Droppy(0);
    let another_droppy = Droppy(1);
    value.get()
}

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)]
  |         ^^^^^^^^^^^^^

解释

微不足道的类型转换是指将类型为 Ue 转换为类型 T,其中 UT 的子类型。这种类型的转换通常是不必要的,因为它通常可以被推断出来。

此 lint 默认设置为 “allow”,因为在某些情况下(例如 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 默认设置为 “allow”,因为在某些情况下(例如 FFI 接口或复杂的类型别名),它会错误地触发,或者在某些情况下,更难以清晰地表达意图。将来有可能将其变为警告,并可能使用显式的强制转换语法,为解决当前问题提供一种便捷的方法。有关历史背景,请参阅 RFC 401(强制转换)RFC 803(类型标注)RFC 3307(移除类型标注)

unit-bindings

unit_bindings lint 检测绑定是无用的情况,因为它们的推断类型为 unit 类型 ()。如果用户使用 unit 类型 () 显式注释了 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)]
  |         ^^^^^^^^^^^^^

解释

使用 unit 类型 () 创建局部绑定没有太多作用,并且可能是用户错误的迹象,例如在以下示例中

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 类型的对象。

unqualified-local-imports

unqualified_local_imports lint 检查使用未以 self::super::crate:: 开头的路径导入本地项的 use 项。

示例

#![warn(unqualified_local_imports)]

mod localmod {
    pub struct S;
}

use localmod::S;
// We have to actually use `S`, or else the `unused` warnings suppress the lint we care about.
pub fn main() {
    let _x = S;
}

这将产生

warning: unknown lint: `unqualified_local_imports`
 --> lint_example.rs:1:9
  |
1 | #![warn(unqualified_local_imports)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: the `unqualified_local_imports` lint is unstable
  = help: add `#![feature(unqualified_local_imports)]` to the crate attributes to enable
  = note: this compiler was built on 2025-02-17; consider upgrading it if it is out of date
  = note: `#[warn(unknown_lints)]` on by default

解释

此 lint 旨在与(不稳定的)rustfmt 设置 group_imports = "StdExternalCrate" 一起使用。该设置使 rustfmt 将 self::super::crate:: 导入与引用其他 crate 的导入分开分组。但是,rustfmt 无法知道 use c::S; 是指本地模块 c 还是外部 crate c,因此它始终被归类为来自另一个 crate 的导入。为了确保来自本地 crate 的导入的一致分组,所有本地导入都必须以 self::super::crate:: 开头。此 lint 可用于强制执行该风格。

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 内的其他地方可访问,但在 crate 外不可访问,则建议使用 pub(crate) 可见性。这更清楚地表达了该项仅在其自身 crate 内可见的意图。

此 lint 默认设置为 “allow”,因为它会为大量现有的 Rust 代码触发,并且存在一些误报。最终,希望将其变为默认警告。

unsafe-attr-outside-unsafe

unsafe_attr_outside_unsafe lint 检测被认为是 unsafe 的属性上缺少 unsafe 关键字的情况。

示例

#![warn(unsafe_attr_outside_unsafe)]

#[no_mangle]
extern "C" fn foo() {}

fn main() {}

这将产生

warning: unsafe attribute used without unsafe
 --> lint_example.rs:3:3
  |
3 | #[no_mangle]
  |   ^^^^^^^^^ usage of unsafe attribute
  |
  = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/unsafe-attributes.html>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(unsafe_attr_outside_unsafe)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: wrap the attribute in `unsafe(...)`
  |
3 | #[unsafe(no_mangle)]
  |   +++++++         +

解释

某些属性(例如 no_mangleexport_namelink_section -- 有关更完整的列表,请参阅 issue #82499)被认为是 “unsafe” 属性。unsafe 属性只能在 unsafe(...) 内部使用。

此 lint 可以自动将属性包装在 unsafe(...) 中,但这显然无法验证 unsafe 属性的前提条件是否已满足,因此这仍然取决于用户。

此 lint 当前默认设置为 “allow”,但这在未来可能会改变。

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 检测不带显式 unsafe 代码块的 unsafe 函数中的 unsafe 操作。

示例

#![deny(unsafe_op_in_unsafe_fn)]

unsafe fn foo() {}

unsafe fn bar() {
    foo();
}

fn main() {}

这将产生

error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe block
 --> lint_example.rs:6:5
  |
6 |     foo();
  |     ^^^^^ call to unsafe function
  |
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
  = 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 操作。将来,希望对其进行更改,以便在没有 unsafe 代码块的情况下,unsafe 操作无法在 unsafe fn 中执行。

对此的修复方法是将 unsafe 代码包装在 unsafe 代码块中。

此 lint 在 2021 版及更早版本中默认设置为 “allow”,从 2024 版开始,默认设置为 “warn”;进一步提高严重性的计划仍在考虑中。有关更多详细信息,请参阅 RFC #2585issue #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 必须在 stable 版本上无条件编译,或者根据 cfg 标志编译,例如允许 stable 用户依赖它们,
  • 不使用 nightly 进行实验性功能,而是仅用于例如不稳定的选项,

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

unused-crate-dependencies

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

示例

#![deny(unused_crate_dependencies)]

这将产生

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

解释

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

此 lint 默认设置为 “allow”,因为它可能会根据构建系统的配置提供误报。例如,当使用 Cargo 时,“package” 由多个 crate(例如库和二进制文件)组成,但依赖项是为整个 package 定义的。如果存在一个仅在二进制文件中使用,但在库中未使用的依赖项,则会在库中错误地发出 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 edition 中使用 extern crate 已不再是惯用做法,因为 extern crate 现在已自动添加到作用域中。

此 lint 默认设置为 “allow”,因为它可能会很嘈杂,并产生误报。如果要从项目中删除依赖项,建议将其从构建配置(例如 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 默认设置为 “allow”,因为它仅强制执行一种风格选择。

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 不同,后者在整个宏从未使用时触发,而此 lint 在宏的其他已使用的单个未使用规则时触发。仅当 unused_macros 不会触发时,unused_macro_rules 才会触发。

示例

#[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: rule #2 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)]
  |        ^^^^^^^^^^^^^^^^^^

解释

未使用的宏规则可能表示错误或未完成的代码。此外,它们会减慢编译速度。目前,不支持在单个规则级别上使警告静音,因此您必须为整个宏定义添加 allow。

如果您打算导出宏以使其在 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 默认设置为 “allow”,因为它有点吹毛求疵,并且不表示实际问题,而只是一种风格选择,并且在重构或移动代码时可能会很嘈杂。

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 lintunused_results lint 本质上是相同的,但会为所有返回值触发。

此 lint 默认设置为 “allow”,因为它可能会很嘈杂,并且可能不是实际问题。例如,调用 VecHashMapremove 方法会返回先前的值,您可能不在意该值。使用此 lint 将需要显式忽略或丢弃此类值。

variant-size-differences

variant_size_differences lint 检测变体大小差异很大的枚举。

示例

#![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 倍以上,则会触发此 lint。

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

此 lint 默认设置为 “allow”,因为它可能会很嘈杂,并且可能不是实际问题。关于此的决策应以分析和基准测试为指导。