默认警告的 Lint

这些 lint 默认都设置为“warn”级别。

abi-unsupported-vector-types

abi_unsupported_vector_types lint 检测 ABI 依赖于启用某些目标功能的函数定义和调用,但这些功能未启用。

示例

extern "C" fn missing_target_feature(_: std::arch::x86_64::__m256) {
  todo!()
}

#[target_feature(enable = "avx")]
unsafe extern "C" fn with_target_feature(_: std::arch::x86_64::__m256) {
  todo!()
}

fn main() {
  let v = unsafe { std::mem::zeroed() };
  unsafe { with_target_feature(v); }
}
warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
 --> lint_example.rs:18:12
  |
  |   unsafe { with_target_feature(v); }
  |            ^^^^^^^^^^^^^^^^^^^^^^ function called here
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
  = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")])
  = note: `#[warn(abi_unsupported_vector_types)]` on by default


warning: ABI error: this function definition uses a avx vector type, which is not enabled
 --> lint_example.rs:3:1
  |
  | pub extern "C" fn with_target_feature(_: std::arch::x86_64::__m256) {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
  = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")])

解释

__m256 的 C ABI 要求该值在 AVX 寄存器中传递,这只有在启用 avx 目标功能时才有可能。因此,如果没有该目标功能,则无法编译 missing_target_feature。当不启用 avx 目标功能的函数调用 with_target_feature 时,会触发类似(但互补)的消息。

请注意,此 lint 与 gcc/clang 中的 -Wpsabi 警告非常相似。

ambiguous-glob-imports

ambiguous_glob_imports lint 检测应该报告歧义错误,但以前由于 rustc 错误而未报告的 glob 导入。

示例

#![deny(ambiguous_glob_imports)]
pub fn foo() -> u32 {
    use sub::*;
    C
}

mod sub {
    mod mod1 { pub const C: u32 = 1; }
    mod mod2 { pub const C: u32 = 2; }

    pub use mod1::*;
    pub use mod2::*;
}

这将产生

error: `C` is ambiguous
  --> lint_example.rs:5:5
   |
5  |     C
   |     ^ ambiguous name
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
   = note: ambiguous because of multiple glob imports of a name in the same module
note: `C` could refer to the constant imported here
  --> lint_example.rs:12:13
   |
12 |     pub use mod1::*;
   |             ^^^^^^^
   = help: consider adding an explicit import of `C` to disambiguate
note: `C` could also refer to the constant imported here
  --> lint_example.rs:13:13
   |
13 |     pub use mod2::*;
   |             ^^^^^^^
   = help: consider adding an explicit import of `C` to disambiguate
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(ambiguous_glob_imports)]
   |         ^^^^^^^^^^^^^^^^^^^^^^

解释

以前版本的 Rust 成功编译了它,因为它在解析 use sub::mod2::* 时丢失了歧义错误。

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

ambiguous-glob-reexports

ambiguous_glob_reexports lint 检测通过 glob 重新导出名称发生冲突的情况。尝试使用从多个 glob 重新导出的相同名称的下游用户将收到警告,指出相同名称的重新定义。

示例

#![deny(ambiguous_glob_reexports)]
pub mod foo {
    pub type X = u8;
}

pub mod bar {
    pub type Y = u8;
    pub type X = u8;
}

pub use foo::*;
pub use bar::*;


pub fn main() {}

这将产生

error: ambiguous glob re-exports
  --> lint_example.rs:11:9
   |
11 | pub use foo::*;
   |         ^^^^^^ the name `X` in the type namespace is first re-exported here
12 | pub use bar::*;
   |         ------ but the name `X` in the type namespace is also re-exported here
   |
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(ambiguous_glob_reexports)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^

解释

这以前是被接受的,但它可能会悄悄地破坏 crate 的下游用户代码。例如,如果在添加 bar::X 到重新导出之前重新导出了 foo::*bar::*,则下游用户可以无问题地使用 this_crate::X。但是,添加 bar::X 会导致下游 crate 中出现编译错误,因为 Xthis_crate 的同一命名空间中定义了多次。

ambiguous-wide-pointer-comparisons

ambiguous_wide_pointer_comparisons lint 检查 *const/*mut ?Sized 作为操作数的比较。

示例

struct A;
struct B;

trait T {}
impl T for A {}
impl T for B {}

let ab = (A, B);
let a = &ab.0 as *const dyn T;
let b = &ab.1 as *const dyn T;

let _ = a == b;

这将产生

warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
  --> lint_example.rs:13:9
   |
13 | let _ = a == b;
   |         ^^^^^^
   |
   = note: `#[warn(ambiguous_wide_pointer_comparisons)]` on by default
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
   |
13 | let _ = std::ptr::addr_eq(a, b);
   |         ++++++++++++++++++ ~  +

解释

比较包括可能未预期的元数据。

anonymous-parameters

anonymous_parameters lint 检测 trait 定义中的匿名参数。

示例

#![deny(anonymous_parameters)]
// edition 2015
pub trait Foo {
    fn foo(usize);
}
fn main() {}

这将产生

error: anonymous parameters are deprecated and will be removed in the next edition
 --> lint_example.rs:4:12
  |
4 |     fn foo(usize);
  |            ^^^^^ help: try naming the parameter or explicitly ignoring it: `_: usize`
  |
  = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
  = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(anonymous_parameters)]
  |         ^^^^^^^^^^^^^^^^^^^^

解释

此语法主要是历史遗留问题,可以通过添加 _ 模式或描述性标识符来轻松解决

trait Foo {
    fn foo(_: usize);
}

此语法现在在 2018 版本中是硬错误。在 2015 版本中,此 lint 默认是“warn”。此 lint 启用带有 --edition 标志的 cargo fix 工具,以自动将旧代码从 2015 版本过渡到 2018 版本。该工具将运行此 lint 并自动应用编译器建议的修复(即向每个参数添加 _)。这提供了一种完全自动化的方式来更新新版本的旧代码。有关更多详细信息,请参见 issue #41686

array-into-iter

array_into_iter lint 检测在数组上调用 into_iter

示例

#![allow(unused)]
[1, 2, 3].into_iter().for_each(|n| { *n; });

这将产生

warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
 --> lint_example.rs:3:11
  |
3 | [1, 2, 3].into_iter().for_each(|n| { *n; });
  |           ^^^^^^^^^
  |
  = warning: this changes meaning in Rust 2021
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
  = note: `#[warn(array_into_iter)]` on by default
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
  |
3 | [1, 2, 3].iter().for_each(|n| { *n; });
  |           ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
  |
3 | IntoIterator::into_iter([1, 2, 3]).for_each(|n| { *n; });
  | ++++++++++++++++++++++++         ~

解释

自 Rust 1.53 起,数组实现了 IntoIterator。但是,为了避免破坏,Rust 2015 和 2018 代码中的 array.into_iter() 仍然会像 (&array).into_iter() 一样运行,返回一个引用迭代器,就像在 Rust 1.52 及更早版本中一样。这仅适用于方法调用语法 array.into_iter(),不适用于任何其他语法,例如 for _ in arrayIntoIterator::into_iter(array)

asm-sub-register

asm_sub_register lint 检测仅使用寄存器子集进行内联汇编输入。

示例

#[cfg(target_arch="x86_64")]
use std::arch::asm;

fn main() {
    #[cfg(target_arch="x86_64")]
    unsafe {
        asm!("mov {0}, {0}", in(reg) 0i16);
    }
}

这将产生

warning: formatting may not be suitable for sub-register argument
 --> src/main.rs:7:19
  |
7 |         asm!("mov {0}, {0}", in(reg) 0i16);
  |                   ^^^  ^^^           ---- for this argument
  |
  = note: `#[warn(asm_sub_register)]` on by default
  = help: use the `x` modifier to have the register formatted as `ax`
  = help: or use the `r` modifier to keep the default formatting of `rax`

解释

某些架构上的寄存器可以使用不同的名称来引用寄存器的子集。默认情况下,编译器将使用完整寄存器大小的名称。要显式使用寄存器的子集,您可以使用模板字符串操作数上的修饰符来覆盖默认值,以指定何时使用子寄存器。如果您传入的值的数据类型小于默认寄存器大小,则会发出此 lint,以提醒您可能使用了不正确的宽度。要解决此问题,请将建议的修饰符添加到模板,或将值强制转换为正确的大小。

有关更多详细信息,请参见参考中的 寄存器模板修饰符

async-fn-in-trait

async_fn_in_trait lint 检测在公共可访问 trait 的定义中使用 async fn

示例

pub trait Trait {
    async fn method(&self);
}
fn main() {}

这将产生

warning: use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
 --> lint_example.rs:2:5
  |
2 |     async fn method(&self);
  |     ^^^^^
  |
  = note: you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
  = note: `#[warn(async_fn_in_trait)]` on by default
help: you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change
  |
2 -     async fn method(&self);
2 +     fn method(&self) -> impl std::future::Future<Output = ()> + Send;
  |

解释

在 trait 定义中使用 async fn 时,trait 不保证关联函数或方法返回的不透明 Future 将实现任何 自动 trait,例如 Send。这可能会令人惊讶,并可能使 trait 上的关联函数或方法不如预期有用。在从 crate 公开的 trait 上,这可能会影响下游 crate,其作者无法更改 trait 定义。

例如,此代码无效

pub trait Trait {
    async fn method(&self) {}
}

fn test<T: Trait>(x: T) {
    fn spawn<T: Send>(_: T) {}
    spawn(x.method()); // Not OK.
}

此 lint 的存在是为了警告公共可访问 trait 的作者,他们可能需要考虑将 async fn 取消语法糖化为返回不透明 impl Future<..> + Send 类型的普通 fn

例如,代替

pub trait Trait {
    async fn method(&self) {}
}

trait 的作者可能想写

use core::future::Future;
pub trait Trait {
    fn method(&self) -> impl Future<Output = ()> + Send { async {} }
}

这仍然允许在 trait 的 impls 中使用 async fn。但是,这也意味着 trait 将永远与方法的返回 Future 未实现 Send 的 impls 不兼容。

相反,如果 trait 仅在本地使用,如果从未使用在泛型函数中,或者如果仅在不关心返回的 Future 是否实现 Send 的单线程上下文中使用,则可以禁止此 lint。

bad-asm-style

bad_asm_style lint 检测 .intel_syntax.att_syntax 指令的使用。

示例

#[cfg(target_arch="x86_64")]
use std::arch::asm;

fn main() {
    #[cfg(target_arch="x86_64")]
    unsafe {
        asm!(
            ".att_syntax",
            "movq %{0}, %{0}", in(reg) 0usize
        );
    }
}

这将产生

warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
 --> src/main.rs:8:14
  |
8 |             ".att_syntax",
  |              ^^^^^^^^^^^
  |
  = note: `#[warn(bad_asm_style)]` on by default

解释

在 x86 上,asm! 默认使用 intel 汇编语法。虽然可以使用汇编器指令(如 .att_syntax)切换此语法,但建议改用 att_syntax 选项,因为它还将正确地为 AT&T 语法要求的寄存器占位符添加 % 前缀。

bare-trait-object

lint bare-trait-object 已重命名为 bare-trait-objects

bare-trait-objects

bare_trait_objects lint 建议为 trait 对象使用 dyn Trait

示例

trait Trait { }

fn takes_trait_object(_: Box<Trait>) {
}

这将产生

warning: trait objects without an explicit `dyn` are deprecated
 --> lint_example.rs:4:30
  |
4 | fn takes_trait_object(_: Box<Trait>) {
  |                              ^^^^^
  |
  = 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/warnings-promoted-to-error.html>
  = note: `#[warn(bare_trait_objects)]` on by default
help: if this is a dyn-compatible trait, use `dyn`
  |
4 | fn takes_trait_object(_: Box<dyn Trait>) {
  |                              +++

解释

如果没有 dyn 指示符,则在阅读代码时,不清楚您看到的是否是 trait 对象,这可能会造成歧义或混淆。dyn 关键字使其显式化,并增加了与 impl Trait 对比的对称性。

boxed-slice-into-iter

boxed_slice_into_iter lint 检测在 boxed slice 上调用 into_iter

示例

#![allow(unused)]
vec![1, 2, 3].into_boxed_slice().into_iter().for_each(|n| { *n; });

这将产生

warning: this method call resolves to `<&Box<[T]> as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<Box<[T]> as IntoIterator>::into_iter` in Rust 2024
 --> lint_example.rs:3:34
  |
3 | vec![1, 2, 3].into_boxed_slice().into_iter().for_each(|n| { *n; });
  |                                  ^^^^^^^^^
  |
  = warning: this changes meaning in Rust 2024
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/intoiterator-box-slice.html>
  = note: `#[warn(boxed_slice_into_iter)]` on by default
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
  |
3 | vec![1, 2, 3].into_boxed_slice().iter().for_each(|n| { *n; });
  |                                  ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
  |
3 | IntoIterator::into_iter(vec![1, 2, 3].into_boxed_slice()).for_each(|n| { *n; });
  | ++++++++++++++++++++++++                                ~

解释

自 Rust 1.80.0 起,boxed slice 实现了 IntoIterator。但是,为了避免破坏,Rust 2015、2018 和 2021 代码中的 boxed_slice.into_iter() 仍然会像 (&boxed_slice).into_iter() 一样运行,返回一个引用迭代器,就像在 Rust 1.79.0 及更早版本中一样。这仅适用于方法调用语法 boxed_slice.into_iter(),不适用于任何其他语法,例如 for _ in boxed_sliceIntoIterator::into_iter(boxed_slice)

break-with-label-and-loop

break_with_label_and_loop lint 检测带有标签的 break 表达式,其值表达式为未标记的循环。

示例

'label: loop {
    break 'label loop { break 42; };
};

这将产生

warning: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression
 --> lint_example.rs:3:5
  |
3 |     break 'label loop { break 42; };
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(break_with_label_and_loop)]` on by default
help: wrap this expression in parentheses
  |
3 |     break 'label (loop { break 42; });
  |                  +                  +

解释

在 Rust 中,循环可以具有标签,并且 break 表达式可以引用该标签以跳出特定循环(而不一定是内部循环)。break 表达式也可以携带值表达式,该值表达式可以是另一个循环。带有标签的 break,其值表达式为未标记的循环,很容易与带有标记循环的未标记 break 混淆,因此不建议使用(但为了兼容性而允许);在循环表达式周围使用括号以消除此警告。带有标记循环的未标记 break 表达式会产生硬错误,也可以通过将表达式包装在括号中来消除。

clashing-extern-declarations

clashing_extern_declarations lint 检测到当 extern fn 已使用相同的名称但不同的类型声明时。

示例

mod m {
    extern "C" {
        fn foo();
    }
}

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

这将产生

warning: `foo` redeclared with a different signature
 --> lint_example.rs:9:5
  |
4 |         fn foo();
  |         --------- `foo` previously declared here
...
9 |     fn foo(_: u32);
  |     ^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
  |
  = note: expected `unsafe extern "C" fn()`
             found `unsafe extern "C" fn(u32)`
  = note: `#[warn(clashing_extern_declarations)]` on by default

解释

由于在链接时,两个相同名称的符号无法解析为两个不同的函数,并且一个函数不可能有两种类型,因此冲突的 extern 声明几乎可以肯定是错误。检查以确保 extern 定义正确且等效,并可能考虑将它们统一在一个位置。

此 lint 不在 crate 之间运行,因为项目可能具有依赖项,这些依赖项都依赖于相同的 extern 函数,但是以不同的(但有效)方式声明它。例如,它们都可能为一个或多个参数声明不透明类型(这将最终成为不同的类型),或者使用在定义 extern fn 的语言中是有效转换的类型。在这些情况下,编译器无法说冲突的声明是不正确的。

coherence-leak-check

coherence_leak_check lint 检测仅通过旧的泄漏检查代码区分的 trait 的冲突实现。

示例

trait SomeTrait { }
impl SomeTrait for for<'a> fn(&'a u8) { }
impl<'a> SomeTrait for fn(&'a u8) { }

这将产生

warning: conflicting implementations of trait `SomeTrait` for type `for<'a> fn(&'a u8)`
 --> lint_example.rs:4:1
  |
3 | impl SomeTrait for for<'a> fn(&'a u8) { }
  | ------------------------------------- first implementation here
4 | impl<'a> SomeTrait for fn(&'a u8) { }
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a u8)`
  |
  = warning: the behavior may change in a future release
  = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
  = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
  = note: `#[warn(coherence_leak_check)]` on by default

解释

过去,编译器会接受仅在 lifetime binder 出现位置不同的相同函数的 trait 实现。由于 borrow checker 实现的更改修复了几个错误,因此不再允许这样做。但是,由于这会影响现有代码,因此这是一个 未来不兼容 的 lint,以便将来过渡到硬错误。

依赖于此模式的代码应引入“newtypes”,例如 struct Foo(for<'a> fn(&'a u8))

有关更多详细信息,请参见 issue #56105

confusable-idents

confusable_idents lint 检测标识符之间视觉上容易混淆的对。

示例

// Latin Capital Letter E With Caron
pub const Ě: i32 = 1;
// Latin Capital Letter E With Breve
pub const Ĕ: i32 = 2;

这将产生

warning: found both `Ě` and `Ĕ` as identifiers, which look alike
 --> lint_example.rs:5:11
  |
3 | pub const Ě: i32 = 1;
  |           - other identifier used here
4 | // Latin Capital Letter E With Breve
5 | pub const Ĕ: i32 = 2;
  |           ^ this identifier can be confused with `Ě`
  |
  = note: `#[warn(confusable_idents)]` on by default

解释

当不同的标识符在视觉上可能看起来相似时,此 lint 会发出警告,这可能会引起混淆。

可混淆检测算法基于 Unicode® 技术标准 #39 Unicode 安全机制第 4 节可混淆检测。对于每个不同的标识符 X,执行函数 skeleton(X)。如果同一 crate 中存在两个不同的标识符 X 和 Y,其中 skeleton(X) = skeleton(Y),则报告它。编译器使用相同的机制来检查标识符是否与关键字过于相似。

请注意,可混淆字符集可能会随时间变化。请注意,如果您“禁止”此 lint,则现有代码将来可能会失败。

const-evaluatable-unchecked

const_evaluatable_unchecked lint 检测类型中使用的泛型常量。

示例

const fn foo<T>() -> usize {
    if std::mem::size_of::<*mut T>() < 8 { // size of *mut T does not depend on T
        4
    } else {
        8
    }
}

fn test<T>() {
    let _ = [0; foo::<T>()];
}

这将产生

warning: cannot use constants which depend on generic parameters in types
  --> lint_example.rs:11:17
   |
11 |     let _ = [0; foo::<T>()];
   |                 ^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
   = note: `#[warn(const_evaluatable_unchecked)]` on by default

解释

在 1.43 版本中,意外地允许在数组重复表达式中使用泛型参数。这是一个 未来不兼容 的 lint,以便将来过渡到硬错误。有关更详细的描述和可能的修复程序,请参见 issue #76200

const-item-mutation

const_item_mutation lint 检测尝试修改 const 项。

示例

const FOO: [i32; 1] = [0];

fn main() {
    FOO[0] = 1;
    // This will print "[0]".
    println!("{:?}", FOO);
}

这将产生

warning: attempting to modify a `const` item
 --> lint_example.rs:4:5
  |
4 |     FOO[0] = 1;
  |     ^^^^^^^^^^
  |
  = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified
note: `const` item defined here
 --> lint_example.rs:1:1
  |
1 | const FOO: [i32; 1] = [0];
  | ^^^^^^^^^^^^^^^^^^^
  = note: `#[warn(const_item_mutation)]` on by default

解释

尝试直接修改 const 项几乎总是错误的。上面示例中发生的情况是,修改了 const 的临时副本,但原始 const 没有被修改。每次您按名称(例如上面示例中的 FOO)引用 const 时,都会在该位置内联该值的单独副本。

此 lint 检查直接写入字段(FOO.field = some_value)或数组条目(FOO[0] = val),或获取对 const 项的可变引用(&mut FOO),包括通过自动解引用(FOO.some_mut_self_method())。

根据您要完成的任务,有多种替代方案

  • 首先,始终重新考虑使用可变全局变量,因为它们可能难以正确使用,并且会使代码更难以使用或理解。
  • 如果您尝试对全局变量执行一次性初始化
    • 如果该值可以在编译时计算,请考虑使用 const 兼容值(请参见 常量求值)。
    • 对于更复杂的单次初始化情况,请考虑使用 std::sync::LazyLock
  • 如果您确实需要可变全局变量,请考虑使用 static,它有多种选项
    • 简单的数据类型可以直接使用 atomic 类型定义和修改。
    • 更复杂的类型可以放在同步原语中,例如 Mutex,可以使用上面列出的选项之一进行初始化。
    • 可变 static 是一种低级原语,需要 unsafe。通常,应避免使用它,而优先使用更高级别的东西,例如上述之一。

dangling-pointers-from-temporaries

dangling_pointers_from_temporaries lint 检测到从临时数据获取指针,该临时数据将立即被丢弃。

示例

#![allow(unused)]
unsafe fn use_data(ptr: *const u8) { }
fn gather_and_use(bytes: impl Iterator<Item = u8>) {
    let x: *const u8 = bytes.collect::<Vec<u8>>().as_ptr();
    unsafe { use_data(x) }
}

这将产生

warning: a dangling pointer will be produced because the temporary `Vec<u8>` will be dropped
 --> lint_example.rs:5:51
  |
5 |     let x: *const u8 = bytes.collect::<Vec<u8>>().as_ptr();
  |                        -------------------------- ^^^^^^ this pointer will immediately be invalid
  |                        |
  |                        this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
  |
  = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
  = help: for more information, see <https://doc.rust-lang.net.cn/reference/destructors.html>
  = note: `#[warn(dangling_pointers_from_temporaries)]` on by default

解释

从临时值获取指针不会延长其生命周期,这意味着该值可能会在指针仍然存在时被丢弃并释放分配,从而使指针悬空。这不是错误(就类型系统而言),但可能也不是用户想要的结果。

如果您需要更强的保证,请考虑使用引用,因为它们由 borrow-checker 静态验证,永远不会悬空。

dead-code

dead_code lint 检测未使用的、未导出的项。

示例

fn foo() {}

这将产生

warning: function `foo` is never used
 --> lint_example.rs:2:4
  |
2 | fn foo() {}
  |    ^^^
  |
  = note: `#[warn(dead_code)]` on by default

解释

死代码可能表示错误或未完成的代码。要消除单个项的警告,请在名称前加上下划线,例如 _foo。如果打算在 crate 外部公开该项,请考虑添加可见性修饰符,例如 pub

为了保留具有未使用字段的元组结构的编号,请将未使用的字段更改为具有单元类型或使用 PhantomData

否则,请考虑删除未使用的代码。

局限性

删除仅用于副作用且从不读取的字段将导致行为更改。这方面的示例包括

  • 如果字段的值在被丢弃时执行操作。
  • 如果字段的类型未实现自动 trait(例如 SendSyncUnpin)。

对于丢弃字段值产生的副作用,应允许在这些字段上使用此 lint。对于包含字段类型产生的副作用,应使用 PhantomData

dependency-on-unit-never-type-fallback

dependency_on_unit_never_type_fallback lint 检测代码在使用 never type fallback() 时编译,但在 fallback 为 ! 时将停止编译的情况。

示例

#![deny(dependency_on_unit_never_type_fallback)]
fn main() {
    if true {
        // return has type `!` which, is some cases, causes never type fallback
        return
    } else {
        // the type produced by this call is not specified explicitly,
        // so it will be inferred from the previous branch
        Default::default()
    };
    // depending on the fallback, this may compile (because `()` implements `Default`),
    // or it may not (because `!` does not implement `Default`)
}

这将产生

error: this function depends on never type fallback being `()`
 --> lint_example.rs:2:1
  |
2 | fn main() {
  | ^^^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/never-type-fallback.html>
  = help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
 --> lint_example.rs:9:9
  |
9 |         Default::default()
  |         ^^^^^^^^^^^^^^^^^^
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(dependency_on_unit_never_type_fallback)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use `()` annotations to avoid fallback changes
  |
9 |         <() as Default>::default()
  |         ++++++        +

解释

由于历史原因,never type fallback 是 (),这意味着 ! 会自发地强制转换为 ()。有计划更改它,但它们可能会使上面的代码无法编译。您应该显式指定类型,而不是依赖于 fallback

if true {
    return
} else {
    // type is explicitly specified, fallback can't hurt us no more
    <() as Default>::default()
};

请参见 Tracking Issue for making ! fall back to !

deprecated

deprecated lint 检测已弃用项的使用。

示例

#[deprecated]
fn foo() {}

fn bar() {
    foo();
}

这将产生

warning: use of deprecated function `main::foo`
 --> lint_example.rs:6:5
  |
6 |     foo();
  |     ^^^
  |
  = note: `#[warn(deprecated)]` on by default

解释

可以使用 deprecated 属性 将项标记为“已弃用”,以指示不应再使用它们。通常,该属性应包含有关应使用什么替代项的注释,或查看文档。

deprecated-where-clause-location

deprecated_where_clause_location lint 检测关联类型中等号前面的 where 子句。

示例

trait Trait {
  type Assoc<'a> where Self: 'a;
}

impl Trait for () {
  type Assoc<'a> where Self: 'a = ();
}

这将产生

warning: where clause not allowed here
 --> lint_example.rs:7:18
  |
7 |   type Assoc<'a> where Self: 'a = ();
  |                  ^^^^^^^^^^^^^^
  |
  = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
  = note: `#[warn(deprecated_where_clause_location)]` on by default
help: move it to the end of the type declaration
  |
7 -   type Assoc<'a> where Self: 'a = ();
7 +   type Assoc<'a>  = () where Self: 'a;
  |

解释

关联类型的 where 子句的首选位置是在类型之后。但是,对于大多数泛型关联类型开发,仅在等号之前接受它。为了提供过渡期并进一步评估此更改,目前两者都被接受。在将来的某个时间点,可能会在版本边界处不允许这样做;但是,目前尚未决定。

deref-into-dyn-supertrait

Deref 实现的 Output 类型为 dyn SuperTrait 时,会输出 deref_into_dyn_supertrait lint。

trait_upcasting 功能稳定后,这些实现将被隐藏。deref 函数将不再被隐式调用,因此可能会发生行为更改。

示例

#![deny(deref_into_dyn_supertrait)]
#![allow(dead_code)]

use core::ops::Deref;

trait A {}
trait B: A {}
impl<'a> Deref for dyn 'a + B {
    type Target = dyn A;
    fn deref(&self) -> &Self::Target {
        todo!()
    }
}

fn take_a(_: &dyn A) { }

fn take_b(b: &dyn B) {
    take_a(b);
}

这将产生

error: this `Deref` implementation is covered by an implicit supertrait coercion
  --> lint_example.rs:9:1
   |
9  | impl<'a> Deref for dyn 'a + B {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
10 |     type Target = dyn A;
   |     -------------------- target type is a supertrait of `dyn B`
   |
   = warning: this will change its meaning in a future release!
   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(deref_into_dyn_supertrait)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^

解释

dyn upcasting 强制转换功能添加了新的强制转换规则,这些规则优先于某些其他强制转换规则,这将导致某些行为更改。

deref-nullptr

deref_nullptr lint 检测到何时解引用空指针,这会导致 未定义的行为

示例

#![allow(unused)]
use std::ptr;
unsafe {
    let x = &*ptr::null::<i32>();
    let x = ptr::addr_of!(*ptr::null::<i32>());
    let x = *(0 as *const i32);
}

这将产生

warning: dereferencing a null pointer
 --> lint_example.rs:5:14
  |
5 |     let x = &*ptr::null::<i32>();
  |              ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
  |
  = note: `#[warn(deref_nullptr)]` on by default


warning: dereferencing a null pointer
 --> lint_example.rs:7:13
  |
7 |     let x = *(0 as *const i32);
  |             ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed

解释

如果访问(从空指针加载或存储到空指针),则解引用空指针会导致 未定义的行为

drop-bounds

drop_bounds lint 检查以 std::ops::Drop 作为边界的泛型。

示例

fn foo<T: Drop>() {}

这将产生

warning: bounds on `T: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped
 --> lint_example.rs:2:11
  |
2 | fn foo<T: Drop>() {}
  |           ^^^^
  |
  = note: `#[warn(drop_bounds)]` on by default

解释

形式为 T: Drop 的泛型 trait 边界很可能具有误导性,并且不是程序员的意图(他们可能应该使用 std::mem::needs_drop 代替)。

Drop 边界实际上并未指示类型是否可以被简单地丢弃,因为包含 Drop 类型的复合类型不一定自身实现 Drop。天真地,人们可能会试图编写一个实现,该实现假设类型可以被简单地丢弃,同时还为实际上调用析构函数的 T: Drop 提供专门化。但是,当 TString 时,这会崩溃,String 本身不实现 Drop,但包含实现 DropVec,因此假设 T 可以被简单地丢弃将导致内存泄漏。

此外,Drop trait 仅包含一个方法 Drop::drop,该方法在用户代码中可能不会显式调用(E0040),因此在 trait 边界中使用 Drop 实际上没有用例,除非可能是一些晦涩的极端情况,可以使用 #[allow(drop_bounds)]

dropping-copy-types

dropping_copy_types lint 检查对具有派生 Copy trait 的值调用 std::mem::drop

示例

let x: i32 = 42; // i32 implements Copy
std::mem::drop(x); // A copy of x is passed to the function, leaving the
                   // original unaffected

这将产生

warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
 --> lint_example.rs:3:1
  |
3 | std::mem::drop(x); // A copy of x is passed to the function, leaving the
  | ^^^^^^^^^^^^^^^-^
  |                |
  |                argument has type `i32`
  |
  = note: `#[warn(dropping_copy_types)]` on by default
help: use `let _ = ...` to ignore the expression or result
  |
3 - std::mem::drop(x); // A copy of x is passed to the function, leaving the
3 + let _ = x; // A copy of x is passed to the function, leaving the
  |

解释

调用 std::mem::drop 对于实现 Copy 的类型没有任何作用,因为该值将被复制并移动到调用时的函数中。

dropping-references

dropping_references lint 检查对引用而不是拥有的值调用 std::mem::drop

示例

fn operation_that_requires_mutex_to_be_unlocked() {} // just to make it compile
let mutex = std::sync::Mutex::new(1); // just to make it compile
let mut lock_guard = mutex.lock();
std::mem::drop(&lock_guard); // Should have been drop(lock_guard), mutex
// still locked
operation_that_requires_mutex_to_be_unlocked();

这将产生

warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
 --> lint_example.rs:5:1
  |
5 | std::mem::drop(&lock_guard); // Should have been drop(lock_guard), mutex
  | ^^^^^^^^^^^^^^^-----------^
  |                |
  |                argument has type `&Result<MutexGuard<'_, i32>, PoisonError<MutexGuard<'_, i32>>>`
  |
  = note: `#[warn(dropping_references)]` on by default
help: use `let _ = ...` to ignore the expression or result
  |
5 - std::mem::drop(&lock_guard); // Should have been drop(lock_guard), mutex
5 + let _ = &lock_guard; // Should have been drop(lock_guard), mutex
  |

解释

对引用调用 drop 只会丢弃引用本身,这是一个空操作。它不会对底层引用的值调用 drop 方法(来自 Drop trait 实现),这很可能是预期的结果。

duplicate-macro-attributes

duplicate_macro_attributes lint 检测到何时在项上复制了类似 #[test] 的内置宏属性。此 lint 可能会在 benchcfg_evaltesttest_case 上触发。

示例

#[test]
#[test]
fn foo() {}

这将产生

warning: duplicated attribute
 --> src/lib.rs:2:1
  |
2 | #[test]
  | ^^^^^^^
  |
  = note: `#[warn(duplicate_macro_attributes)]` on by default

解释

重复的属性可能错误地源自复制粘贴,并且重复属性的效果可能不明显或不理想。

例如,将 #[test] 属性加倍会注册该测试运行两次,而其环境没有任何变化。

dyn-drop

dyn_drop lint 检查具有 std::ops::Drop 的 trait 对象。

示例

fn foo(_x: Box<dyn Drop>) {}

这将产生

warning: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
 --> lint_example.rs:2:20
  |
2 | fn foo(_x: Box<dyn Drop>) {}
  |                    ^^^^
  |
  = note: `#[warn(dyn_drop)]` on by default

解释

形式为 dyn Drop 的 trait 对象边界很可能具有误导性,并且不是程序员的意图。

Drop 边界实际上并未指示类型是否可以被简单地丢弃,因为包含 Drop 类型的复合类型不一定自身实现 Drop。天真地,人们可能会试图编写一个延迟丢弃系统,以将清理内存从延迟敏感的代码路径中拉出来,使用 dyn Drop trait 对象。但是,当 TString 时,这会崩溃,String 不实现 Drop,但可能应该被接受。

要编写接受任何内容的 trait 对象边界,请使用具有 blanket 实现的占位符 trait。

trait Placeholder {}
impl<T> Placeholder for T {}
fn foo(_x: Box<dyn Placeholder>) {}

elided-named-lifetimes

elided_named_lifetimes lint 检测到何时省略的 lifetime 最终成为命名 lifetime,例如 'static 或某些 lifetime 参数 'a

示例

#![deny(elided_named_lifetimes)]
struct Foo;
impl Foo {
    pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
        unsafe { &mut *(x as *mut _) }
    }
}

这将产生

error: elided lifetime has a name
 --> lint_example.rs:5:50
  |
5 |     pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
  |                                                  ^ this elided lifetime gets resolved as `'static`
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(elided_named_lifetimes)]
  |         ^^^^^^^^^^^^^^^^^^^^^^
help: consider specifying it explicitly
  |
5 |     pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 {
  |                                                   +++++++

解释

Lifetime 省略非常有用,因为它使您无需为每个 lifetime 命名,但有时它可能会产生一些令人惊讶的解析。在安全代码中,这通常是可以的,因为 borrow checker 会阻止任何不健全性,因此最坏的情况是您在其他地方获得令人困惑的错误消息。但是对于 unsafe 代码,这种意外的解析可能会导致不健全的代码。

ellipsis-inclusive-range-patterns

ellipsis_inclusive_range_patterns lint 检测 ... 范围模式,该模式已弃用。

示例

let x = 123;
match x {
    0...100 => {}
    _ => {}
}

这将产生

warning: `...` range patterns are deprecated
 --> lint_example.rs:4:6
  |
4 |     0...100 => {}
  |      ^^^ help: use `..=` for an inclusive range
  |
  = 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/warnings-promoted-to-error.html>
  = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default

解释

... 范围模式语法已更改为 ..=,以避免与 .. 范围表达式 混淆。请改用新形式。

exported-private-dependencies

exported_private_dependencies lint 检测在公共接口中公开的私有依赖项。

示例

pub fn foo() -> Option<some_private_dependency::Thing> {
    None
}

这将产生

warning: type `bar::Thing` from private dependency 'bar' in public interface
 --> src/lib.rs:3:1
  |
3 | pub fn foo() -> Option<bar::Thing> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(exported_private_dependencies)]` on by default

解释

依赖项可以标记为“私有”,以指示它们未在 crate 的公共接口中公开。Cargo 可以使用它来独立解析这些依赖项,因为它可以假设它不需要将它们与使用相同依赖项的其他包统一起来。此 lint 指示违反了该合同。

要解决此问题,请避免在公共接口中公开依赖项。或者,将依赖项切换为公共依赖项。

请注意,对此的支持仅在 nightly 频道上可用。有关更多详细信息,请参见 RFC 1977,以及 Cargo 文档

for-loops-over-fallibles

for_loops_over_fallibles lint 检查对 OptionResult 值使用 for 循环。

示例

let opt = Some(1);
for x in opt { /* ... */}

这将产生

warning: for loop over an `Option`. This is more readably written as an `if let` statement
 --> lint_example.rs:3:10
  |
3 | for x in opt { /* ... */}
  |          ^^^
  |
  = note: `#[warn(for_loops_over_fallibles)]` on by default
help: to check pattern in a loop use `while let`
  |
3 | while let Some(x) = opt { /* ... */}
  | ~~~~~~~~~~~~~~~ ~~~
help: consider using `if let` to clear intent
  |
3 | if let Some(x) = opt { /* ... */}
  | ~~~~~~~~~~~~ ~~~

解释

OptionResult 都实现了 IntoIterator trait,这允许在 for 循环中使用它们。对 OptionResultfor 循环将迭代 0 次(如果值为 None/Err(_))或 1 次(如果值为 Some(_)/Ok(_))。这不是很实用,并且通过 if let 可以更清楚地表达。

for 循环也可能被意外地编写为打算多次调用函数,而该函数返回 Some(_),在这些情况下,应改用 while let 循环。

OptionResultIntoIterator 实现的“预期”用途是将它们传递给期望实现 IntoIterator 的通用代码。例如,使用 .chain(option) 可选地向迭代器添加值。

forbidden-lint-groups

forbidden_lint_groups lint 检测应用于 lint 组的 forbid 的违规行为。由于编译器中的错误,这些曾经被完全忽略。它们现在生成警告。

示例

#![forbid(warnings)]
#![warn(bad_style)]

fn main() {}

这将产生

warning: warn(bad_style) incompatible with previous forbid
 --> lint_example.rs:2:9
  |
1 | #![forbid(warnings)]
  |           -------- `forbid` level set here
2 | #![warn(bad_style)]
  |         ^^^^^^^^^ overruled by previous forbid
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
  = note: `#[warn(forbidden_lint_groups)]` on by default

如果您的 crate 使用 #![forbid(warnings)],我们建议您更改为 #![deny(warnings)]

解释

由于编译器错误,将 forbid 应用于 lint 组以前没有任何效果。该错误现已修复,但为了避免破坏现有 crate,我们发布此未来兼容性警告,而不是强制执行 forbid

forgetting-copy-types

forgetting_copy_types lint 检查对具有派生 Copy trait 的值调用 std::mem::forget

示例

let x: i32 = 42; // i32 implements Copy
std::mem::forget(x); // A copy of x is passed to the function, leaving the
                     // original unaffected

这将产生

warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
 --> lint_example.rs:3:1
  |
3 | std::mem::forget(x); // A copy of x is passed to the function, leaving the
  | ^^^^^^^^^^^^^^^^^-^
  |                  |
  |                  argument has type `i32`
  |
  = note: `#[warn(forgetting_copy_types)]` on by default
help: use `let _ = ...` to ignore the expression or result
  |
3 - std::mem::forget(x); // A copy of x is passed to the function, leaving the
3 + let _ = x; // A copy of x is passed to the function, leaving the
  |

解释

调用 std::mem::forget 对于实现 Copy 的类型没有任何作用,因为该值将被复制并移动到调用时的函数中。

另一种同样有效的解释是,Copy 类型不实现 Drop trait,这意味着它们没有析构函数。没有析构函数,std::mem::forget 就没有什么可以忽略的。

forgetting-references

forgetting_references lint 检查对引用而不是拥有的值调用 std::mem::forget

示例

let x = Box::new(1);
std::mem::forget(&x); // Should have been forget(x), x will still be dropped

这将产生

warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
 --> lint_example.rs:3:1
  |
3 | std::mem::forget(&x); // Should have been forget(x), x will still be dropped
  | ^^^^^^^^^^^^^^^^^--^
  |                  |
  |                  argument has type `&Box<i32>`
  |
  = note: `#[warn(forgetting_references)]` on by default
help: use `let _ = ...` to ignore the expression or result
  |
3 - std::mem::forget(&x); // Should have been forget(x), x will still be dropped
3 + let _ = &x; // Should have been forget(x), x will still be dropped
  |

解释

对引用调用 forget 只会忘记引用本身,这是一个空操作。它不会忘记底层引用的值,这很可能是预期的结果。

function-item-references

function_item_references lint 检测使用 fmt::Pointer 格式化或 transmuted 的函数引用。

示例

fn foo() { }

fn main() {
    println!("{:p}", &foo);
}

这将产生

warning: taking a reference to a function item does not give a function pointer
 --> lint_example.rs:4:22
  |
4 |     println!("{:p}", &foo);
  |                      ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn()`
  |
  = note: `#[warn(function_item_references)]` on by default

解释

获取函数的引用可能会被误认为是获取指向该函数的指针的一种方式。当将引用格式化为指针或 transmute 它时,这可能会产生意外的结果。当函数引用被格式化为指针,作为受 fmt::Pointer 约束的参数传递或 transmute 时,会发出此 lint。

hidden-glob-reexports

hidden_glob_reexports lint 检测 glob 重新导出项被私有项隐藏的情况。

示例

#![deny(hidden_glob_reexports)]

pub mod upstream {
    mod inner { pub struct Foo {}; pub struct Bar {}; }
    pub use self::inner::*;
    struct Foo {} // private item shadows `inner::Foo`
}

// mod downstream {
//     fn test() {
//         let _ = crate::upstream::Foo; // inaccessible
//     }
// }

pub fn main() {}

这将产生

error: private item shadows public glob re-export
 --> lint_example.rs:6:5
  |
6 |     struct Foo {} // private item shadows `inner::Foo`
  |     ^^^^^^^^^^^^^
  |
note: the name `Foo` in the type namespace is supposed to be publicly re-exported here
 --> lint_example.rs:5:13
  |
5 |     pub use self::inner::*;
  |             ^^^^^^^^^^^^^^
note: but the private item here shadows it
 --> lint_example.rs:6:5
  |
6 |     struct Foo {} // private item shadows `inner::Foo`
  |     ^^^^^^^^^^^^^
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(hidden_glob_reexports)]
  |         ^^^^^^^^^^^^^^^^^^^^^

解释

这以前被接受,没有任何错误或警告,但它可能会悄悄地破坏 crate 的下游用户代码。如果添加了 struct Foo,则 dep::inner::Foo 将悄悄地变得不可访问,并在下游使用站点触发“struct Foo is private”可见性错误。

improper-ctypes

improper_ctypes lint 检测在外部模块中不正确地使用类型。

示例

extern "C" {
    static STATIC: String;
}

这将产生

warning: `extern` block uses type `String`, which is not FFI-safe
 --> lint_example.rs:3:20
  |
3 |     static STATIC: String;
  |                    ^^^^^^ not FFI-safe
  |
  = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
  = note: this struct has unspecified layout
  = note: `#[warn(improper_ctypes)]` on by default

解释

编译器有多个检查来验证 extern 块中使用的类型是否安全并遵循某些规则,以确保与外部接口的正确兼容性。当它检测到定义中可能存在的错误时,会发出此 lint。该 lint 通常应提供问题的描述,以及可能的有关如何解决该问题的提示。

improper-ctypes-definitions

improper_ctypes_definitions lint 检测不正确地使用 extern 函数定义。

示例

#![allow(unused)]
pub extern "C" fn str_type(p: &str) { }

这将产生

warning: `extern` fn uses type `str`, which is not FFI-safe
 --> lint_example.rs:3:31
  |
3 | pub extern "C" fn str_type(p: &str) { }
  |                               ^^^^ not FFI-safe
  |
  = help: consider using `*const u8` and a length instead
  = note: string slices have no C equivalent
  = note: `#[warn(improper_ctypes_definitions)]` on by default

解释

extern 函数中可以指定许多与给定 ABI 不兼容的参数和返回类型。此 lint 警告不应使用这些类型。该 lint 通常应提供问题的描述,以及可能的有关如何解决该问题的提示。

incomplete-features

incomplete_features lint 检测使用 feature 属性 启用的不稳定功能,这些功能在某些或所有情况下可能无法正常运行。

示例

#![feature(generic_const_exprs)]

这将产生

warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
 --> lint_example.rs:1:12
  |
1 | #![feature(generic_const_exprs)]
  |            ^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
  = note: `#[warn(incomplete_features)]` on by default

解释

尽管鼓励人们尝试使用不稳定功能,但其中一些功能已知是不完整或有缺陷的。此 lint 表示该功能尚未完成,您可能会遇到问题。

inline-no-sanitize

inline_no_sanitize lint 检测到 #[inline(always)]#[no_sanitize(...) 的不兼容使用。

示例

#![feature(no_sanitize)]

#[inline(always)]
#[no_sanitize(address)]
fn x() {}

fn main() {
    x()
}

这将产生

warning: `no_sanitize` will have no effect after inlining
 --> lint_example.rs:4:1
  |
4 | #[no_sanitize(address)]
  | ^^^^^^^^^^^^^^^^^^^^^^^
  |
note: inlining requested here
 --> lint_example.rs:3:1
  |
3 | #[inline(always)]
  | ^^^^^^^^^^^^^^^^^
  = note: `#[warn(inline_no_sanitize)]` on by default

解释

使用 #[inline(always)] 属性会阻止 #[no_sanitize(...) 属性生效。考虑暂时移除 inline 属性。

internal-features

internal_features lint 检测到使用 feature 属性启用的不稳定特性,这些特性是编译器或标准库内部的。

示例

#![feature(rustc_attrs)]

这将产生

warning: the feature `rustc_attrs` is internal to the compiler or standard library
 --> lint_example.rs:1:12
  |
1 | #![feature(rustc_attrs)]
  |            ^^^^^^^^^^^
  |
  = note: using it is strongly discouraged
  = note: `#[warn(internal_features)]` on by default

解释

这些特性是编译器和标准库的实现细节,不应在用户代码中使用。

invalid-from-utf8

invalid_from_utf8 lint 检查对 std::str::from_utf8std::str::from_utf8_mut 的调用,这些调用使用了已知的无效 UTF-8 值。

示例

#[allow(unused)]
std::str::from_utf8(b"Ru\x82st");

这将产生

warning: calls to `std::str::from_utf8` with a invalid literal always return an error
 --> lint_example.rs:3:1
  |
3 | std::str::from_utf8(b"Ru\x82st");
  | ^^^^^^^^^^^^^^^^^^^^-----------^
  |                     |
  |                     the literal was valid UTF-8 up to the 2 bytes
  |
  = note: `#[warn(invalid_from_utf8)]` on by default

解释

根据 std::str::from_utf8std::str::from_utf8_mut 的文档,尝试创建这样的 str 总是会返回错误。

invalid-macro-export-arguments

invalid_macro_export_arguments lint 检测到 #[macro_export] 与无效参数一起使用的情况。

示例

#![deny(invalid_macro_export_arguments)]

#[macro_export(invalid_parameter)]
macro_rules! myMacro {
   () => {
        // [...]
   }
}

#[macro_export(too, many, items)]

这将产生

error: `invalid_parameter` isn't a valid `#[macro_export]` argument
 --> lint_example.rs:4:16
  |
4 | #[macro_export(invalid_parameter)]
  |                ^^^^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(invalid_macro_export_arguments)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

唯一有效的参数是 #[macro_export(local_inner_macros)] 或没有参数 (#[macro_export])。在 #[macro_export(..)] 中不能有多个参数,也不能提及 local_inner_macros 以外的参数。

invalid-nan-comparisons

invalid_nan_comparisons lint 检查以 f32::NANf64::NAN 作为操作数之一的比较。

示例

let a = 2.3f32;
if a == f32::NAN {}

这将产生

warning: incorrect NaN comparison, NaN cannot be directly compared to itself
 --> lint_example.rs:3:4
  |
3 | if a == f32::NAN {}
  |    ^^^^^^^^^^^^^
  |
  = note: `#[warn(invalid_nan_comparisons)]` on by default
help: use `f32::is_nan()` or `f64::is_nan()` instead
  |
3 - if a == f32::NAN {}
3 + if a.is_nan() {}
  |

解释

NaN 与任何事物都不能进行有意义的比较——甚至包括它自己——因此这些比较总是为假。

invalid-value

invalid_value lint 检测到创建无效值的情况,例如空引用。

示例

#![allow(unused)]
unsafe {
    let x: &'static i32 = std::mem::zeroed();
}

这将产生

warning: the type `&i32` does not permit zero-initialization
 --> lint_example.rs:4:27
  |
4 |     let x: &'static i32 = std::mem::zeroed();
  |                           ^^^^^^^^^^^^^^^^^^
  |                           |
  |                           this code causes undefined behavior when executed
  |                           help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
  |
  = note: references must be non-null
  = note: `#[warn(invalid_value)]` on by default

解释

在某些情况下,编译器可以检测到代码正在创建无效值,这应该避免。

特别是,此 lint 将检查对 mem::zeroedmem::uninitializedmem::transmuteMaybeUninit::assume_init 的不当使用,这些不当使用可能会导致 未定义行为。该 lint 应该提供额外的信息来指示问题所在以及可能的解决方案。

irrefutable-let-patterns

irrefutable_let_patterns lint 检测 不可反驳模式if letwhile letif let 守卫中的使用。

示例

if let _ = 123 {
    println!("always runs!");
}

这将产生

warning: irrefutable `if let` pattern
 --> lint_example.rs:2:4
  |
2 | if let _ = 123 {
  |    ^^^^^^^^^^^
  |
  = note: this pattern will always match, so the `if let` is useless
  = help: consider replacing the `if let` with a `let`
  = note: `#[warn(irrefutable_let_patterns)]` on by default

解释

通常在 if letwhile let 语句中没有理由使用不可反驳模式,因为该模式总是会成功匹配。 letloop 语句就足够了。但是,当使用宏生成代码时,禁止不可反驳模式将需要在宏不知道模式是否可反驳的情况下进行笨拙的变通。此 lint 允许宏接受这种形式,同时警告在正常代码中可能存在不正确的用法。

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

large-assignments

large_assignments lint 检测到大型类型的对象正在被移动时。

示例

let x = [0; 50000];
let y = x;

produces

warning: moving a large value
  --> $DIR/move-large.rs:1:3
  let y = x;
          - Copied large value here

解释

当在普通赋值或函数参数中使用大型类型时,惯用的代码可能会效率低下。理想情况下,适当的优化会解决这个问题,但这种优化只是尽力而为。此 lint 将在所有大型移动的位置触发,从而允许用户在代码中解决它们。

late-bound-lifetime-arguments

late_bound_lifetime_arguments lint 检测路径段中带有后期绑定生命周期参数的泛型生命周期参数。

示例

struct S;

impl S {
    fn late(self, _: &u8, _: &u8) {}
}

fn main() {
    S.late::<'static>(&0, &0);
}

这将产生

warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
 --> lint_example.rs:8:14
  |
4 |     fn late(self, _: &u8, _: &u8) {}
  |                      - the late bound lifetime parameter is introduced here
...
8 |     S.late::<'static>(&0, &0);
  |              ^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
  = note: `#[warn(late_bound_lifetime_arguments)]` on by default

解释

目前尚不清楚如何为早期绑定生命周期参数提供参数,如果它们与同一列表中的后期绑定参数混合在一起。目前,如果存在后期绑定参数,则提供任何显式参数都将触发此 lint,以便将来可以在不影响向后兼容性的情况下采用解决方案。这是一个 未来不兼容 的 lint,目的是将来将其转换为硬错误。有关更多详细信息,以及早期和后期绑定参数之间差异的描述,请参阅 issue #42868

legacy-derive-helpers

legacy_derive_helpers lint 检测在引入之前使用的 derive 辅助属性。

示例

#[serde(rename_all = "camelCase")]
#[derive(Deserialize)]
struct S { /* fields */ }

produces

warning: derive helper attribute is used before it is introduced
  --> $DIR/legacy-derive-helpers.rs:1:3
   |
 1 | #[serde(rename_all = "camelCase")]
   |   ^^^^^
...
 2 | #[derive(Deserialize)]
   |          ----------- the attribute is introduced here

解释

这样的属性由于历史原因而起作用,但是属性扩展通常以从左到右的顺序工作,因此,为了解析 #[serde],编译器必须尝试“展望未来”,查看项目中尚未扩展的部分,但是这种尝试并不总是可靠的。

要修复此警告,请将辅助属性放在其对应的 derive 之后。

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct S { /* fields */ }

map-unit-fn

map_unit_fn lint 检查 Iterator::map 接收返回 () 的可调用对象的情况。

示例

fn foo(items: &mut Vec<u8>) {
    items.sort();
}

fn main() {
    let mut x: Vec<Vec<u8>> = vec![
        vec![0, 2, 1],
        vec![5, 4, 3],
    ];
    x.iter_mut().map(foo);
}

这将产生

warning: `Iterator::map` call that discard the iterator's values
  --> lint_example.rs:10:18
   |
1  | fn foo(items: &mut Vec<u8>) {
   | --------------------------- this function returns `()`, which is likely not what you wanted
...
10 |     x.iter_mut().map(foo);
   |                  ^^^^---^
   |                  |   |
   |                  |   called `Iterator::map` with callable that returns `()`
   |                  after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
   |
   = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
   = note: `#[warn(map_unit_fn)]` on by default
help: you might have meant to use `Iterator::for_each`
   |
10 |     x.iter_mut().for_each(foo);
   |                  ~~~~~~~~

解释

映射到 () 几乎总是一个错误。

mixed-script-confusables

mixed_script_confusables lint 检测不同脚本之间标识符中视觉上容易混淆的字符。

示例

// The Japanese katakana character エ can be confused with the Han character 工.
const エ: &'static str = "アイウ";

这将产生

warning: the usage of Script Group `Japanese, Katakana` in this crate consists solely of mixed script confusables
 --> lint_example.rs:3:7
  |
3 | const エ: &'static str = "アイウ";
  |       ^^
  |
  = note: the usage includes 'エ' (U+30A8)
  = note: please recheck to make sure their usages are indeed what you want
  = note: `#[warn(mixed_script_confusables)]` on by default

解释

当不同脚本之间的字符可能在视觉上看起来相似时,此 lint 会发出警告,这可能会导致混淆。

如果 crate 包含同一脚本中具有非混淆字符的其他标识符,则不会发出此 lint。例如,如果上面给出的示例有另一个带有片假名字符的标识符(例如 let カタカナ = 123;),则这表明您有意使用片假名,并且不会对此发出警告。

请注意,可混淆字符集可能会随时间变化。请注意,如果您“禁止”此 lint,则现有代码将来可能会失败。

named-arguments-used-positionally

named_arguments_used_positionally lint 检测到在格式字符串中仅按位置使用命名参数的情况。这种用法是有效的,但可能非常令人困惑。

示例

#![deny(named_arguments_used_positionally)]
fn main() {
    let _x = 5;
    println!("{}", _x = 1); // Prints 1, will trigger lint

    println!("{}", _x); // Prints 5, no lint emitted
    println!("{_x}", _x = _x); // Prints 5, no lint emitted
}

这将产生

error: named argument `_x` is not used by name
 --> lint_example.rs:4:20
  |
4 |     println!("{}", _x = 1); // Prints 1, will trigger lint
  |               --   ^^ this named argument is referred to by position in formatting string
  |               |
  |               this formatting argument uses named argument `_x` by position
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(named_arguments_used_positionally)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use the named argument by name to avoid ambiguity
  |
4 |     println!("{_x}", _x = 1); // Prints 1, will trigger lint
  |                ++

解释

Rust 格式化字符串可以通过位置引用命名参数,但这种用法可能令人困惑。特别是,读者可能会错误地认为命名参数的声明是赋值(这将产生 unit 类型)。为了向后兼容,这不是一个硬错误。

never-type-fallback-flowing-into-unsafe

never_type_fallback_flowing_into_unsafe lint 检测到 never type fallback 影响不安全函数调用的情况。

Never type fallback

当编译器看到 ! 类型的值时,它会隐式地插入一个强制转换(如果可能),以允许类型检查推断任何类型

// this
let x: u8 = panic!();

// is (essentially) turned by the compiler into
let x: u8 = absurd(panic!());

// where absurd is a function with the following signature
// (it's sound, because `!` always marks unreachable code):
fn absurd<T>(never: !) -> T { ... }

虽然在一个分支中使用非发散代码(例如 if a { b } else { return })很方便,但这可能会导致编译错误

// this
{ panic!() };

// gets turned into this
{ absurd(panic!()) }; // error: can't infer the type of `absurd`

为了防止此类错误,编译器会记住它插入 absurd 调用的位置,如果它无法推断出它们的类型,则会将类型设置为 fallback。 { absurd::(panic!()) };。这就是所谓的 “never type fallback”。

示例

#![deny(never_type_fallback_flowing_into_unsafe)]
fn main() {
    if true {
        // return has type `!` which, is some cases, causes never type fallback
        return
    } else {
        // `zeroed` is an unsafe function, which returns an unbounded type
        unsafe { std::mem::zeroed() }
    };
    // depending on the fallback, `zeroed` may create `()` (which is completely sound),
    // or `!` (which is instant undefined behavior)
}

这将产生

error: never type fallback affects this call to an `unsafe` function
 --> lint_example.rs:8:18
  |
8 |         unsafe { std::mem::zeroed() }
  |                  ^^^^^^^^^^^^^^^^^^
  |
  = warning: this changes meaning in Rust 2024 and in a future release in all editions!
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/never-type-fallback.html>
  = help: specify the type explicitly
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(never_type_fallback_flowing_into_unsafe)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use `()` annotations to avoid fallback changes
  |
8 |         unsafe { std::mem::zeroed::<()>() }
  |                                  ++++++

解释

由于历史原因,never type fallback 曾经是 (),这意味着 ! 会自发地强制转换为 ()。有计划更改这一点,但这可能会使上面的代码变得不健全。与其依赖 fallback,不如显式指定类型

if true {
    return
} else {
    // type is explicitly specified, fallback can't hurt us no more
    unsafe { std::mem::zeroed::<()>() }
};

请参见 Tracking Issue for making ! fall back to !

no-mangle-generic-items

no_mangle_generic_items lint 检测必须进行名称修饰的泛型项。

示例

#[no_mangle]
fn foo<T>(t: T) {

}

这将产生

warning: functions generic over types or consts must be mangled
 --> lint_example.rs:3:1
  |
2 |   #[no_mangle]
  |   ------------ help: remove this attribute
3 | / fn foo<T>(t: T) {
4 | |
5 | | }
  | |_^
  |
  = note: `#[warn(no_mangle_generic_items)]` on by default

解释

带有泛型的函数必须对其符号进行名称修饰,以适应泛型参数。 no_mangle 属性 在这种情况下不起作用,应该删除。

non-fmt-panic

lint non-fmt-panic 已重命名为 non-fmt-panics

non-camel-case-types

non_camel_case_types lint 检测不使用驼峰命名法的类型、变体、trait 和类型参数。

示例

struct my_struct;

这将产生

warning: type `my_struct` should have an upper camel case name
 --> lint_example.rs:2:8
  |
2 | struct my_struct;
  |        ^^^^^^^^^ help: convert the identifier to upper camel case: `MyStruct`
  |
  = note: `#[warn(non_camel_case_types)]` on by default

解释

这些标识符的首选风格是使用“驼峰命名法”,例如 MyStruct,其中首字母不应小写,并且字母之间不应使用下划线。标识符的开头和结尾以及非字母之间(例如 X86_64)允许使用下划线。

non-contiguous-range-endpoints

non_contiguous_range_endpoints lint 检测在使用互斥 范围模式 时可能出现的差一错误。

示例

let x = 123u32;
match x {
    0..100 => { println!("small"); }
    101..1000 => { println!("large"); }
    _ => { println!("larger"); }
}

这将产生

warning: multiple ranges are one apart
 --> lint_example.rs:4:5
  |
4 |     0..100 => { println!("small"); }
  |     ^^^^^^
  |     |
  |     this range doesn't match `100_u32` because `..` is an exclusive range
  |     help: use an inclusive range instead: `0_u32..=100_u32`
5 |     101..1000 => { println!("large"); }
  |     --------- this could appear to continue range `0_u32..100_u32`, but `100_u32` isn't matched by either of them
  |
  = note: `#[warn(non_contiguous_range_endpoints)]` on by default

解释

在 match 表达式中使用范围模式而遗漏单个数字可能是一个错误。检查开头和结尾值是否是您期望的值,并记住 ..= 的右边界是包含的,而 .. 的右边界是互斥的。

non-fmt-panics

non_fmt_panics lint 检测 panic!(..) 调用,其中第一个参数不是格式化字符串。

示例

panic!("{}");
panic!(123);

这将产生

warning: panic message contains an unused formatting placeholder
 --> lint_example.rs:2:9
  |
2 | panic!("{}");
  |         ^^
  |
  = note: this message is not used as a format string when given without arguments, but will be in Rust 2021
  = note: `#[warn(non_fmt_panics)]` on by default
help: add the missing argument
  |
2 | panic!("{}", ...);
  |            +++++
help: or add a "{}" format string to use the message literally
  |
2 | panic!("{}", "{}");
  |        +++++


warning: panic message is not a string literal
 --> lint_example.rs:3:8
  |
3 | panic!(123);
  |        ^^^
  |
  = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
help: add a "{}" format string to `Display` the message
  |
3 | panic!("{}", 123);
  |        +++++
help: or use std::panic::panic_any instead
  |
3 | std::panic::panic_any(123);
  | ~~~~~~~~~~~~~~~~~~~~~

解释

在 Rust 2018 及更早版本中,panic!(x) 直接使用 x 作为消息。这意味着 panic!("{}") 会以 "{}" 作为消息 panic,而不是将其用作格式化字符串,而 panic!(123) 将以 i32 作为消息 panic。

Rust 2021 始终将第一个参数解释为格式化字符串。

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, `impl` blocks should be written at the same level as their item
 --> lint_example.rs:7:5
  |
6 | fn foo() {
  | -------- move the `impl` block outside of this function `foo` and up 2 bodies
7 |     impl MyTrait for MyStruct {}
  |     ^^^^^-------^^^^^--------
  |          |           |
  |          |           `MyStruct` is not local
  |          `MyTrait` is not local
  |
  = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![warn(non_local_definitions)]
  |         ^^^^^^^^^^^^^^^^^^^^^

解释

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

如果 impl 定义嵌套在项内部,并且类型和 trait 都不与 impl 块处于相同的嵌套级别,则该 impl 定义是非本地的。

所有嵌套主体(函数、枚举判别式、数组长度、consts)(顶级模块中的 const _: Ty = { ... } 除外,这仍未决定)都会被检查。

non-shorthand-field-patterns

non_shorthand_field_patterns lint 检测到在模式中使用 Struct { x: x } 而不是 Struct { x }

示例

struct Point {
    x: i32,
    y: i32,
}


fn main() {
    let p = Point {
        x: 5,
        y: 5,
    };

    match p {
        Point { x: x, y: y } => (),
    }
}

这将产生

warning: the `x:` in this pattern is redundant
  --> lint_example.rs:14:17
   |
14 |         Point { x: x, y: y } => (),
   |                 ^^^^ help: use shorthand field pattern: `x`
   |
   = note: `#[warn(non_shorthand_field_patterns)]` on by default


warning: the `y:` in this pattern is redundant
  --> lint_example.rs:14:23
   |
14 |         Point { x: x, y: y } => (),
   |                       ^^^^ help: use shorthand field pattern: `y`

解释

首选风格是避免重复指定字段名称和绑定名称,如果两个标识符相同。

non-snake-case

non_snake_case lint 检测不使用蛇形命名法的变量、方法、函数、生命周期参数和模块。

示例

let MY_VALUE = 5;

这将产生

warning: variable `MY_VALUE` should have a snake case name
 --> lint_example.rs:2:5
  |
2 | let MY_VALUE = 5;
  |     ^^^^^^^^ help: convert the identifier to snake case: `my_value`
  |
  = note: `#[warn(non_snake_case)]` on by default

解释

这些标识符的首选风格是使用“蛇形命名法”,其中所有字符均为小写,单词之间用单个下划线分隔,例如 my_value

non-upper-case-globals

non_upper_case_globals lint 检测不使用大写标识符的静态项。

示例

static max_points: i32 = 5;

这将产生

warning: static variable `max_points` should have an upper case name
 --> lint_example.rs:2:8
  |
2 | static max_points: i32 = 5;
  |        ^^^^^^^^^^ help: convert the identifier to upper case: `MAX_POINTS`
  |
  = note: `#[warn(non_upper_case_globals)]` on by default

解释

静态项名称的首选风格是使用全大写字母,例如 MAX_POINTS

noop-method-call

noop_method_call lint 检测对 noop 方法的特定调用,例如调用 Clone::clone,其中 T: !Clone

示例

#![allow(unused)]
struct Foo;
let foo = &Foo;
let clone: &Foo = foo.clone();

这将产生

warning: call to `.clone()` on a reference in this situation does nothing
 --> lint_example.rs:5:22
  |
5 | let clone: &Foo = foo.clone();
  |                      ^^^^^^^^
  |
  = note: the type `Foo` does not implement `Clone`, so calling `clone` on `&Foo` copies the reference, which does not do anything and can be removed
  = note: `#[warn(noop_method_call)]` on by default
help: remove this redundant call
  |
5 - let clone: &Foo = foo.clone();
5 + let clone: &Foo = foo;
  |
help: if you meant to clone `Foo`, implement `Clone` for it
  |
3 + #[derive(Clone)]
4 | struct Foo;
  |

解释

某些方法调用是 noop,意味着它们什么也不做。通常,这些方法是 blanket 实现的结果,这些实现恰好创建了一些最终什么也不做的方法调用。例如,Clone 在所有 &T 上实现,但在 T 未实现 clone 的 &T 上调用 clone 实际上什么也不做,因为引用是 copy 的。此 lint 检测到这些调用并警告用户。

opaque-hidden-inferred-bound

opaque_hidden_inferred_bound lint 检测到关联类型边界中嵌套的 impl Trait 写得不够通用,无法满足关联类型的边界的情况。

解释

此功能在 #97346 中被删除,但随后在 #99860 中被回滚,因为它导致了回归。

我们计划重新引入此功能作为硬错误,但在那之前,此 lint 用于警告并为任何依赖此行为的用例提供修复建议。

示例

#![feature(type_alias_impl_trait)]

trait Duh {}

impl Duh for i32 {}

trait Trait {
    type Assoc: Duh;
}

impl<F: Duh> Trait for F {
    type Assoc = F;
}

type Tait = impl Sized;

fn test() -> impl Trait<Assoc = Tait> {
    42
}

fn main() {}

这将产生

warning: opaque type `impl Trait<Assoc = Tait>` does not satisfy its associated type bounds
  --> lint_example.rs:17:25
   |
8  |     type Assoc: Duh;
   |                 --- this associated type bound is unsatisfied for `Tait`
...
17 | fn test() -> impl Trait<Assoc = Tait> {
   |                         ^^^^^^^^^^^^
   |
   = note: `#[warn(opaque_hidden_inferred_bound)]` on by default

在此示例中,test 声明 impl Trait 的关联类型 Associmpl Sized,这不满足关联类型上的边界 Duh

尽管隐藏类型 i32 确实满足此边界,但我们不认为此 lint 的返回类型是格式良好的。可以通过将 Tait = impl Sized 更改为 Tait = impl Sized + Duh 来修复它。

out-of-scope-macro-calls

out_of_scope_macro_calls lint 检测在 macro_rules 定义之上,当它们不在作用域内时被调用的情况,这可能发生在键值属性中。

示例

#![doc = in_root!()]

macro_rules! in_root { () => { "" } }

fn main() {}

这将产生

warning: cannot find macro `in_root` in this scope
 --> lint_example.rs:1:10
  |
1 | #![doc = in_root!()]
  |          ^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #124535 <https://github.com/rust-lang/rust/issues/124535>
  = help: import `macro_rules` with `use` to make it callable above its definition
  = note: `#[warn(out_of_scope_macro_calls)]` on by default

解释

macro_rules 项可见的作用域从该项开始并向下延伸。这更类似于 let,而不是其他项,其他项在其定义之上和之下都在作用域内。由于一个错误,macro_rules 意外地在其定义之上的一些键值属性内处于作用域内。此 lint 捕获此类情况。要解决此问题,请通过使用 use 导入将 macro_rules 转换为常规作用域项。

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

overlapping-patterns

lint overlapping-patterns 已重命名为 overlapping-range-endpoints

overlapping-range-endpoints

overlapping_range_endpoints lint 检测 match 分支,这些分支的 范围模式 在其端点上重叠。

示例

let x = 123u8;
match x {
    0..=100 => { println!("small"); }
    100..=255 => { println!("large"); }
}

这将产生

warning: multiple patterns overlap on their endpoints
 --> lint_example.rs:5:5
  |
4 |     0..=100 => { println!("small"); }
  |     ------- this range overlaps on `100_u8`...
5 |     100..=255 => { println!("large"); }
  |     ^^^^^^^^^ ... with this range
  |
  = note: you likely meant to write mutually exclusive ranges
  = note: `#[warn(overlapping_range_endpoints)]` on by default

解释

在 match 表达式中使用以这种方式重叠的范围模式可能是一个错误。检查开头和结尾值是否是您期望的值,并记住 ..= 的左右边界都是包含的。

path-statements

path_statements lint 检测没有效果的路径语句。

示例

let x = 42;

x;

这将产生

warning: path statement with no effect
 --> lint_example.rs:4:1
  |
4 | x;
  | ^^
  |
  = note: `#[warn(path_statements)]` on by default

解释

拥有一个没有效果的语句通常是一个错误。

private-bounds

private_bounds lint 检测项的辅助接口中的类型,这些类型比项本身更私有。项的辅助接口由泛型参数和 where 子句上的边界组成,包括 trait 项的 supertrait。

示例

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

struct PrivTy;
pub struct S
    where PrivTy:
{}
fn main() {}

这将产生

error: type `PrivTy` is more private than the item `S`
 --> lint_example.rs:5:1
  |
5 | pub struct S
  | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub`
  |
note: but type `PrivTy` is only usable at visibility `pub(crate)`
 --> lint_example.rs:4:1
  |
4 | struct PrivTy;
  | ^^^^^^^^^^^^^
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![deny(private_bounds)]
  |         ^^^^^^^^^^^^^^

解释

在项边界中使用私有类型或 trait 会使项实际提供的接口不太清晰。

private-interfaces

private_interfaces lint 检测项的主要接口中的类型,这些类型比项本身更私有。项的主要接口是其所有接口,除了泛型参数和 where 子句上的边界。

示例

#![allow(unused)]
#![deny(private_interfaces)]
struct SemiPriv;

mod m1 {
    struct Priv;
    impl crate::SemiPriv {
        pub fn f(_: Priv) {}
    }
}

fn main() {}

这将产生

error: type `Priv` is more private than the item `m1::<impl SemiPriv>::f`
 --> lint_example.rs:8:9
  |
8 |         pub fn f(_: Priv) {}
  |         ^^^^^^^^^^^^^^^^^ associated function `m1::<impl SemiPriv>::f` is reachable at visibility `pub(crate)`
  |
note: but type `Priv` is only usable at visibility `pub(self)`
 --> lint_example.rs:6:5
  |
6 |     struct Priv;
  |     ^^^^^^^^^^^
note: the lint level is defined here
 --> lint_example.rs:2:9
  |
2 | #![deny(private_interfaces)]
  |         ^^^^^^^^^^^^^^^^^^

解释

在主要接口中拥有私有内容保证了由于类型私有性,该项将无法从外部模块使用。

private-macro-use

private_macro_use lint 检测使用 #[macro_use] 导入的私有宏。

示例

// extern_macro.rs
macro_rules! foo_ { () => {}; }
use foo_ as foo;

// code.rs

#![deny(private_macro_use)]

#[macro_use]
extern crate extern_macro;

fn main() {
    foo!();
}

这将产生

error: cannot find macro `foo` in this scope

解释

此 lint 源于忽略对外部 crate 中宏的可见性检查。

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

ptr-cast-add-auto-to-object

ptr_cast_add_auto_to_object lint 检测将原始指针转换为 trait 对象,这会添加 auto trait。

示例

let ptr: *const dyn core::any::Any = &();
_ = ptr as *const dyn core::any::Any + Send;

这将产生

warning: adding an auto trait `Send` to a trait object in a pointer cast may cause UB later on
 --> lint_example.rs:3:5
  |
3 | _ = ptr as *const dyn core::any::Any + Send;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #127323 <https://github.com/rust-lang/rust/issues/127323>
  = note: `#[warn(ptr_cast_add_auto_to_object)]` on by default

解释

添加 auto trait 可能会使 vtable 无效,从而可能在之后的安全代码中导致 UB。例如

#![feature(arbitrary_self_types)]

trait Trait {
    fn f(self: *const Self)
    where
        Self: Send;
}

impl Trait for *const () {
    fn f(self: *const Self) {
        unreachable!()
    }
}

fn main() {
    let unsend: *const () = &();
    let unsend: *const dyn Trait = &unsend;
    let send_bad: *const (dyn Trait + Send) = unsend as _;
    send_bad.f(); // this crashes, since vtable for `*const ()` does not have an entry for `f`
}

通常,在将指针传递给安全代码之前,您必须确保 vtable 对于指针的类型是正确的。

ptr-to-integer-transmute-in-consts

ptr_to_integer_transmute_in_consts lint 检测 const 函数和关联常量中的指针到整数的 transmute。

示例

const fn foo(ptr: *const u8) -> usize {
   unsafe {
       std::mem::transmute::<*const u8, usize>(ptr)
   }
}

这将产生

warning: pointers cannot be transmuted to integers during const eval
 --> lint_example.rs:4:8
  |
4 |        std::mem::transmute::<*const u8, usize>(ptr)
  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: at compile-time, pointers do not have an integer value
  = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
  = help: for more information, see https://doc.rust-lang.net.cn/std/mem/fn.transmute.html
  = note: `#[warn(ptr_to_integer_transmute_in_consts)]` on by default

解释

const 上下文中将指针 transmute 为整数是未定义行为。任何尝试使用生成的整数都会中止 const 求值。

但有时编译器可能不会为 const 函数和关联常量内部的指针到整数的 transmute 发出错误,因为它们仅在被引用时才会被求值。因此,此 lint 用作额外的防御层,以防止任何未定义行为在没有任何警告或错误的情况下编译。

有关更多详细信息,请参阅参考文档中的 std::mem::transmute

redundant-semicolon

lint redundant-semicolon 已重命名为 redundant-semicolons

redundant-semicolons

redundant_semicolons lint 检测不必要的多余分号。

示例

let _ = 123;;

这将产生

warning: unnecessary trailing semicolon
 --> lint_example.rs:2:13
  |
2 | let _ = 123;;
  |             ^ help: remove this semicolon
  |
  = note: `#[warn(redundant_semicolons)]` on by default

解释

不需要额外的分号,可以删除它们以避免混淆和视觉混乱。

refining-impl-trait-internal

refining_impl_trait_internal lint 检测方法签名中的 impl Trait 返回类型,这些返回类型由 trait 实现进行细化,这意味着实现添加了 trait 中不存在的有关返回类型的信息。

示例

#![deny(refining_impl_trait)]

use std::fmt::Display;

trait AsDisplay {
    fn as_display(&self) -> impl Display;
}

impl<'s> AsDisplay for &'s str {
    fn as_display(&self) -> Self {
        *self
    }
}

fn main() {
    // users can observe that the return type of
    // `<&str as AsDisplay>::as_display()` is `&str`.
    let _x: &str = "".as_display();
}

这将产生

error: impl trait in impl method signature does not match trait method signature
  --> lint_example.rs:10:29
   |
6  |     fn as_display(&self) -> impl Display;
   |                             ------------ return type from trait method defined here
...
10 |     fn as_display(&self) -> Self {
   |                             ^^^^
   |
   = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
   = note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(refining_impl_trait)]
   |         ^^^^^^^^^^^^^^^^^^^
   = note: `#[deny(refining_impl_trait_internal)]` implied by `#[deny(refining_impl_trait)]`
help: replace the return type so that it matches the trait
   |
10 |     fn as_display(&self) -> impl std::fmt::Display {
   |                             ~~~~~~~~~~~~~~~~~~~~~~

解释

对于实现已知的类型,方法的调用者能够观察到 impl 签名中编写的类型。这可能是预期的行为,但也可能导致实现细节被意外泄露。特别是,对于不希望对类型做出比 trait 签名中编写的更强保证的库作者来说,这可能会构成 semver 风险。

refining_impl_trait 是一个由两个 lint 组成的 lint 组

  • refining_impl_trait_reachable,用于在 crate 外部可公开访问的细化,以及
  • refining_impl_trait_internal,用于仅在 crate 内部可见的细化。

我们正在寻求对这些 lint 的反馈;有关更多信息,请参阅 issue #121718

refining-impl-trait-reachable

refining_impl_trait_reachable lint 检测方法签名中的 impl Trait 返回类型,这些返回类型由可公开访问的 trait 实现进行细化,这意味着实现添加了 trait 中不存在的有关返回类型的信息。

示例

#![deny(refining_impl_trait)]

use std::fmt::Display;

pub trait AsDisplay {
    fn as_display(&self) -> impl Display;
}

impl<'s> AsDisplay for &'s str {
    fn as_display(&self) -> Self {
        *self
    }
}

fn main() {
    // users can observe that the return type of
    // `<&str as AsDisplay>::as_display()` is `&str`.
    let _x: &str = "".as_display();
}

这将产生

error: impl trait in impl method signature does not match trait method signature
  --> lint_example.rs:10:29
   |
6  |     fn as_display(&self) -> impl Display;
   |                             ------------ return type from trait method defined here
...
10 |     fn as_display(&self) -> Self {
   |                             ^^^^
   |
   = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
   = note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(refining_impl_trait)]
   |         ^^^^^^^^^^^^^^^^^^^
   = note: `#[deny(refining_impl_trait_reachable)]` implied by `#[deny(refining_impl_trait)]`
help: replace the return type so that it matches the trait
   |
10 |     fn as_display(&self) -> impl std::fmt::Display {
   |                             ~~~~~~~~~~~~~~~~~~~~~~

解释

对于实现已知的类型,方法的调用者能够观察到 impl 签名中编写的类型。这可能是预期的行为,但也可能导致实现细节被意外泄露。特别是,对于不希望对类型做出比 trait 签名中编写的更强保证的库作者来说,这可能会构成 semver 风险。

refining_impl_trait 是一个由两个 lint 组成的 lint 组

  • refining_impl_trait_reachable,用于在 crate 外部可公开访问的细化,以及
  • refining_impl_trait_internal,用于仅在 crate 内部可见的细化。

我们正在寻求对这些 lint 的反馈;有关更多信息,请参阅 issue #121718

renamed-and-removed-lints

renamed_and_removed_lints lint 检测已重命名或删除的 lint。

示例

#![deny(raw_pointer_derive)]

这将产生

warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
 --> lint_example.rs:1:9
  |
1 | #![deny(raw_pointer_derive)]
  |         ^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(renamed_and_removed_lints)]` on by default

解释

要修复此问题,请删除 lint 或使用新名称。这可以帮助避免对不再有效的 lint 感到困惑,并有助于维护重命名 lint 的一致性。

repr-transparent-external-private-fields

repr_transparent_external_private_fields lint 检测标记为 #[repr(transparent)] 的类型,这些类型(传递地)包含标记为 #[non_exhaustive] 或包含私有字段的外部 ZST 类型

示例

#![deny(repr_transparent_external_private_fields)]
use foo::NonExhaustiveZst;

#[repr(transparent)]
struct Bar(u32, ([u32; 0], NonExhaustiveZst));

这将产生

error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
 --> src/main.rs:5:28
  |
5 | struct Bar(u32, ([u32; 0], NonExhaustiveZst));
  |                            ^^^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> src/main.rs:1:9
  |
1 | #![deny(repr_transparent_external_private_fields)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
  = note: this struct contains `NonExhaustiveZst`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.

解释

以前,Rust 接受包含外部私有零大小类型的字段,即使向该私有类型添加非零大小字段不应是破坏性更改。

这是一个 未来不兼容 的 lint,目的是将来将其转换为硬错误。有关更多详细信息,请参阅 issue #78586

self-constructor-from-outer-item

self_constructor_from_outer_item lint 检测由于解析器中的错误而静默允许 Self 构造函数的情况,这可能会产生令人惊讶和意外的行为。

从外部项使用 Self 类型别名从来不是预期的,但被静默允许了。这已被弃用——并且当 Self 类型别名引用不在作用域内的泛型时,这是一个硬错误。

示例

#![deny(self_constructor_from_outer_item)]

struct S0(usize);

impl S0 {
    fn foo() {
        const C: S0 = Self(0);
        fn bar() -> S0 {
            Self(0)
        }
    }
}

这将产生

error: can't reference `Self` constructor from outer item
 --> lint_example.rs:8:23
  |
6 | impl S0 {
  | ------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
7 |     fn foo() {
8 |         const C: S0 = Self(0);
  |                       ^^^^ help: replace `Self` with the actual type: `S0`
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #124186 <https://github.com/rust-lang/rust/issues/124186>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(self_constructor_from_outer_item)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


error: can't reference `Self` constructor from outer item
  --> lint_example.rs:10:13
   |
6  | impl S0 {
   | ------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
...
10 |             Self(0)
   |             ^^^^ help: replace `Self` with the actual type: `S0`
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #124186 <https://github.com/rust-lang/rust/issues/124186>

解释

Self 类型别名不应该是可访问的,因为嵌套项不与父项的参数作用域关联。

semicolon-in-expressions-from-macros

semicolon_in_expressions_from_macros lint 检测在表达式位置调用宏时,宏主体中尾随的分号。以前接受过,但正在逐步淘汰。

示例

#![deny(semicolon_in_expressions_from_macros)]
macro_rules! foo {
    () => { true; }
}

fn main() {
    let val = match true {
        true => false,
        _ => foo!()
    };
}

这将产生

error: trailing semicolon in macro used in expression position
 --> lint_example.rs:3:17
  |
3 |     () => { true; }
  |                 ^
...
9 |         _ => foo!()
  |              ------ in this macro invocation
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(semicolon_in_expressions_from_macros)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)

解释

以前,当在表达式位置调用宏时,Rust 会忽略宏主体中尾随的分号。但是,这使得语言中分号的处理不一致,并且可能在某些情况下导致意外的运行时行为(例如,如果宏作者期望值被 drop)。

这是一个 未来不兼容 的 lint,目的是将来将其转换为硬错误。有关更多详细信息,请参阅 issue #79813

special-module-name

special_module_name lint 检测具有特殊含义的文件的模块声明。

示例

mod lib;

fn main() {
    lib::run();
}

这将产生

warning: found module declaration for lib.rs
 --> lint_example.rs:1:1
  |
1 | mod lib;
  | ^^^^^^^^
  |
  = note: lib.rs is the root of this crate's library target
  = help: to refer to it from other targets, use the library's name as the path
  = note: `#[warn(special_module_name)]` on by default

解释

Cargo 将 lib.rsmain.rs 识别为库或二进制 crate 的根,因此将它们声明为模块将导致 crate 编译错误,除非显式配置。

要从同一 crate 中的二进制目标访问库,请使用 your_crate_name:: 作为路径,而不是 lib::

// bar/src/lib.rs
fn run() {
    // ...
}

// bar/src/main.rs
fn main() {
    bar::run();
}

二进制目标不能用作库,因此不允许将二进制目标声明为模块。

stable-features

stable_features lint 检测到已经稳定化的 feature 属性

示例

#![feature(test_accepted_feature)]
fn main() {}

这将产生

warning: the feature `test_accepted_feature` has been stable since 1.0.0 and no longer requires an attribute to enable
 --> lint_example.rs:1:12
  |
1 | #![feature(test_accepted_feature)]
  |            ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(stable_features)]` on by default

解释

当一个特性稳定化后,不再需要为其包含 #![feature] 属性。要修复此问题,只需删除 #![feature] 属性。

static-mut-ref

lint static-mut-ref 已重命名为 static-mut-refs

static-mut-refs

static_mut_refs lint 检查 unsafe 块和 unsafe 函数内部的可变静态变量的共享或可变引用。

示例

fn main() {
    static mut X: i32 = 23;
    static mut Y: i32 = 24;

    unsafe {
        let y = &X;
        let ref x = X;
        let (x, y) = (&X, &Y);
        foo(&X);
    }
}

unsafe fn _foo() {
    static mut X: i32 = 23;
    static mut Y: i32 = 24;

    let y = &X;
    let ref x = X;
    let (x, y) = (&X, &Y);
    foo(&X);
}

fn foo<'a>(_x: &'a i32) {}

这将产生

warning: creating a shared reference to mutable static is discouraged
 --> lint_example.rs:6:17
  |
6 |         let y = &X;
  |                 ^^ shared reference to mutable static
  |
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
  = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
  = note: `#[warn(static_mut_refs)]` on by default
help: use `&raw const` instead to create a raw pointer
  |
6 |         let y = &raw const X;
  |                 ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
 --> lint_example.rs:7:21
  |
7 |         let ref x = X;
  |                     ^ shared reference to mutable static
  |
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
  = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives


warning: creating a shared reference to mutable static is discouraged
 --> lint_example.rs:8:23
  |
8 |         let (x, y) = (&X, &Y);
  |                       ^^ shared reference to mutable static
  |
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
  = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
  |
8 |         let (x, y) = (&raw const X, &Y);
  |                       ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
 --> lint_example.rs:8:27
  |
8 |         let (x, y) = (&X, &Y);
  |                           ^^ shared reference to mutable static
  |
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
  = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
  |
8 |         let (x, y) = (&X, &raw const Y);
  |                           ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
 --> lint_example.rs:9:13
  |
9 |         foo(&X);
  |             ^^ shared reference to mutable static
  |
  = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
  = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
  |
9 |         foo(&raw const X);
  |             ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
  --> lint_example.rs:17:13
   |
17 |     let y = &X;
   |             ^^ shared reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
   |
17 |     let y = &raw const X;
   |             ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
  --> lint_example.rs:18:17
   |
18 |     let ref x = X;
   |                 ^ shared reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives


warning: creating a shared reference to mutable static is discouraged
  --> lint_example.rs:19:19
   |
19 |     let (x, y) = (&X, &Y);
   |                   ^^ shared reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
   |
19 |     let (x, y) = (&raw const X, &Y);
   |                   ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
  --> lint_example.rs:19:23
   |
19 |     let (x, y) = (&X, &Y);
   |                       ^^ shared reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
   |
19 |     let (x, y) = (&X, &raw const Y);
   |                       ~~~~~~~~~~


warning: creating a shared reference to mutable static is discouraged
  --> lint_example.rs:20:9
   |
20 |     foo(&X);
   |         ^^ shared reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.net.cn/nightly/edition-guide/rust-2024/static-mut-references.html>
   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
help: use `&raw const` instead to create a raw pointer
   |
20 |     foo(&raw const X);
   |         ~~~~~~~~~~

解释

可变静态变量的共享或可变引用几乎总是一个错误,并可能导致未定义行为和代码中的各种其他问题。

在 2021 版本之前的版本中,此 lint 默认是 “warn”,在 2024 版本中是 “deny”。

suspicious-double-ref-op

suspicious_double_ref_op lint 检查在 &&T 上使用 .clone()/.borrow()/.deref() 的情况,当 T: !Deref/Borrow/Clone 时,这意味着调用将返回内部 &T,而不是对底层 T 执行操作,这可能会造成混淆。

示例

#![allow(unused)]
struct Foo;
let foo = &&Foo;
let clone: &Foo = foo.clone();

这将产生

warning: using `.clone()` on a double reference, which returns `&Foo` instead of cloning the inner type
 --> lint_example.rs:5:22
  |
5 | let clone: &Foo = foo.clone();
  |                      ^^^^^^^^
  |
  = note: `#[warn(suspicious_double_ref_op)]` on by default

解释

由于 Foo 没有实现 Clone,因此运行 .clone() 仅取消引用双重引用,而不是克隆内部类型,而克隆内部类型才是预期的。

trivial-bounds

trivial_bounds lint 检测不依赖于任何类型参数的 trait 边界。

示例

#![feature(trivial_bounds)]
pub struct A where i32: Copy;

这将产生

warning: trait bound i32: Copy does not depend on any type or lifetime parameters
 --> lint_example.rs:3:25
  |
3 | pub struct A where i32: Copy;
  |                         ^^^^
  |
  = note: `#[warn(trivial_bounds)]` on by default

解释

通常,您不会编写您知道始终为真或永不为真的 trait 边界。但是,当使用宏时,宏可能不知道在生成代码时约束是否成立。目前,如果约束始终为真,编译器不会警告您,如果约束永不为真,则会生成错误。 trivial_bounds 功能将此更改为在两种情况下都发出警告,从而使宏在生成代码时具有更大的自由度和灵活性,同时在编写非宏代码时仍然提供一些信号,表明存在问题。

有关更多详细信息,请参阅 RFC 2056。此功能目前仅在 nightly channel 上可用,请参阅跟踪 issue #48214

type-alias-bounds

type_alias_bounds lint 检测类型别名中的边界。

示例

type SendVec<T: Send> = Vec<T>;

这将产生

warning: bounds on generic parameters in type aliases are not enforced
 --> lint_example.rs:2:17
  |
2 | type SendVec<T: Send> = Vec<T>;
  |               --^^^^
  |               | |
  |               | will not be checked at usage sites of the type alias
  |               help: remove this bound
  |
  = note: this is a known limitation of the type checker that may be lifted in a future edition.
          see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
  = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
  = note: `#[warn(type_alias_bounds)]` on by default

解释

类型别名的泛型参数和 where 子句中的 trait 和生命周期边界在类型别名的使用位置未被检查。此外,它们在其定义位置的正确性也没有像别名类型那样被彻底检查。

这是类型检查器的已知限制,可能会在未来的版本中解除。在这种情况下允许此类边界是无意的。

虽然这些边界可能具有次要影响,例如启用“简写”关联类型路径1的使用,并影响传递给类型别名的 trait 对象类型的默认 trait 对象生命周期2,但在上述类型检查器的限制解除之前,不应允许这样做。

强烈建议不要使用此类边界,因为它们具有积极的误导性。

1

即,T::Assoc 形式的路径,其中 T 是由 trait Trait 限制的类型参数,该 trait 定义了一个名为 Assoc 的关联类型,而不是 <T as Trait>::Assoc 形式的完全限定路径。

tyvar-behind-raw-pointer

tyvar_behind_raw_pointer lint 检测指向推断变量的原始指针。

示例

// edition 2015
let data = std::ptr::null();
let _ = &data as *const *const ();

if data.is_null() {}

这将产生

warning: type annotations needed
 --> lint_example.rs:6:9
  |
6 | if data.is_null() {}
  |         ^^^^^^^
  |
  = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
  = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
  = note: `#[warn(tyvar_behind_raw_pointer)]` on by default

解释

这种推断以前是允许的,但是随着未来 任意 self 类型 的到来,这可能会引入歧义。要解决此问题,请使用显式类型而不是依赖类型推断。

这是一个 未来不兼容 的 lint,目的是在 2018 版本中将其转换为硬错误。有关更多详细信息,请参阅 issue #46906。这目前在 2018 版本中是一个硬错误,在 2015 版本中默认是 “warn”。

uncommon-codepoints

uncommon_codepoints lint 检测标识符中不常见的 Unicode 码位。

示例

#![allow(unused)]
const µ: f64 = 0.000001;

这将产生

warning: identifier contains a non normalized (NFKC) character: 'µ'
 --> lint_example.rs:3:7
  |
3 | const µ: f64 = 0.000001;
  |       ^
  |
  = note: this character is included in the Not_NFKC Unicode general security profile
  = note: `#[warn(uncommon_codepoints)]` on by default

解释

此 lint 警告使用不常用的字符,这些字符可能会导致视觉混淆。

此 lint 由标识符触发,该标识符包含的码位不属于 Unicode® 技术标准 #39 Unicode 安全机制第 3.1 节标识符通用安全配置文件 中描述的“允许”码位集。

请注意,不常见的码位集可能会随时间变化。请注意,如果您“禁止”此 lint,则现有代码将来可能会失败。

unconditional-recursion

unconditional_recursion lint 检测无法在不调用自身的情况下返回的函数。

示例

fn foo() {
    foo();
}

这将产生

warning: function cannot return without recursing
 --> lint_example.rs:2:1
  |
2 | fn foo() {
  | ^^^^^^^^ cannot return without recursing
3 |     foo();
  |     ----- recursive call site
  |
  = help: a `loop` may express intention better if this is on purpose
  = note: `#[warn(unconditional_recursion)]` on by default

解释

拥有一个没有终止条件的递归调用通常是一个错误。如果您真的打算拥有一个无限循环,建议使用 loop 表达式。

uncovered-param-in-projection

uncovered_param_in_projection lint 检测违反了 Rust 孤儿规则之一的情况,该规则针对外部 trait 实现,涉及在 trait 关联类型路径(“投影”)内部使用类型参数,这些路径的输出可能不是本地类型,但被错误地认为“覆盖”了所述参数,这是不健全的,并且可能会被未来版本的编译器拒绝。

最初在 #99554 中报告。

示例

// dependency.rs
#![crate_type = "lib"]

pub trait Trait<T, U> {}
// dependent.rs
trait Identity {
    type Output;
}

impl<T> Identity for T {
    type Output = T;
}

struct Local;

impl<T> dependency::Trait<Local, T> for <T as Identity>::Output {}

fn main() {}

这将产生

warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
  --> dependent.rs:11:6
   |
11 | impl<T> dependency::Trait<Local, T> for <T as Identity>::Output {}
   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #124559 <https://github.com/rust-lang/rust/issues/124559>
   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
   = note: `#[warn(uncovered_param_in_projection)]` on by default

解释

FIXME(fmease): 编写解释。

undefined-naked-function-abi

undefined_naked_function_abi lint 检测未指定 ABI 或指定 Rust ABI 的 naked 函数定义。

示例

#![feature(asm_experimental_arch, naked_functions)]

use std::arch::naked_asm;

#[naked]
pub fn default_abi() -> u32 {
    unsafe { naked_asm!(""); }
}

#[naked]
pub extern "Rust" fn rust_abi() -> u32 {
    unsafe { naked_asm!(""); }
}

这将产生

warning: Rust ABI is unsupported in naked functions
 --> lint_example.rs:7:1
  |
7 | pub fn default_abi() -> u32 {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(undefined_naked_function_abi)]` on by default


warning: Rust ABI is unsupported in naked functions
  --> lint_example.rs:12:1
   |
12 | pub extern "Rust" fn rust_abi() -> u32 {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

解释

Rust ABI 目前是未定义的。因此,naked 函数应指定非 Rust ABI。

unexpected-cfgs

unexpected_cfgs lint 检测意外的条件编译条件。

示例

rustc --check-cfg 'cfg()'
#[cfg(widnows)]
fn foo() {}

这将产生

warning: unexpected `cfg` condition name: `widnows`
 --> lint_example.rs:1:7
  |
1 | #[cfg(widnows)]
  |       ^^^^^^^
  |
  = note: `#[warn(unexpected_cfgs)]` on by default

解释

仅当将 --check-cfg 参数传递给编译器时,此 lint 才处于活动状态,并且每当使用意外的条件名称或值时都会触发。

有关更多详细信息,请参阅 条件配置检查 部分。

有关在 Cargo.toml 中配置此 lint 的信息,请参阅 Cargo Specifics 部分。

unfulfilled-lint-expectations

unfulfilled_lint_expectations lint 检测 lint 期望何时未实现。

示例

#[expect(unused_variables)]
let x = 10;
println!("{}", x);

这将产生

warning: this lint expectation is unfulfilled
 --> lint_example.rs:2:10
  |
2 | #[expect(unused_variables)]
  |          ^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unfulfilled_lint_expectations)]` on by default

解释

#[expect] 属性可用于创建 lint 期望。如果在同一位置的 #[warn] 属性会导致 lint 发射,则期望将被实现。如果期望未实现,因为没有发出 lint,则此 lint 将在属性上发出。

ungated-async-fn-track-caller

ungated_async_fn_track_caller lint 在异步函数上使用 #[track_caller] 属性但未启用相应的不稳定特性标志时发出警告。

示例

#[track_caller]
async fn foo() {}

这将产生

warning: `#[track_caller]` on async functions is a no-op
 --> lint_example.rs:2:1
  |
2 | #[track_caller]
  | ^^^^^^^^^^^^^^^
3 | async fn foo() {}
  | ----------------- this function will not propagate the caller location
  |
  = note: see issue #110011 <https://github.com/rust-lang/rust/issues/110011> for more information
  = help: add `#![feature(async_fn_track_caller)]` 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(ungated_async_fn_track_caller)]` on by default

解释

该属性必须与 async_fn_track_caller feature flag 结合使用。否则,#[track_caller] 注解将作为 no-op 运行。

uninhabited-static

uninhabited_static lint 检测 uninhabited statics。

示例

enum Void {}
extern {
    static EXTERN: Void;
}

这将产生

warning: static of uninhabited type
 --> lint_example.rs:4:5
  |
4 |     static EXTERN: Void;
  |     ^^^^^^^^^^^^^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
  = note: uninhabited statics cannot be initialized, and any access would be an immediate error
  = note: `#[warn(uninhabited_static)]` on by default

解释

具有 uninhabited 类型的静态变量永远无法初始化,因此无法定义。但是,可以使用 extern static 来规避此问题,这会在编译器稍后假设没有初始化的 uninhabited 位置(例如 locals 或 statics)时导致问题。这以前是意外允许的,但正在逐步淘汰。

unknown-lints

unknown_lints lint 检测无法识别的 lint 属性。

示例

#![allow(not_a_real_lint)]

这将产生

warning: unknown lint: `not_a_real_lint`
 --> lint_example.rs:1:10
  |
1 | #![allow(not_a_real_lint)]
  |          ^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unknown_lints)]` on by default

解释

指定不存在的 lint 通常是一个错误。检查拼写,并检查 lint 列表以获取正确的名称。还要考虑您是否正在使用旧版本的编译器,并且该 lint 仅在新版本中可用。

unknown-or-malformed-diagnostic-attributes

unknown_or_malformed_diagnostic_attributes lint 检测无法识别或格式错误的诊断属性。

示例

#![feature(diagnostic_namespace)]
#[diagnostic::does_not_exist]
struct Foo;

这将产生

warning: unknown diagnostic attribute
 --> lint_example.rs:3:15
  |
3 | #[diagnostic::does_not_exist]
  |               ^^^^^^^^^^^^^^
  |
  = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default

解释

指定不存在的诊断属性通常是一个错误。检查拼写,并检查诊断属性列表以获取正确的名称。还要考虑您是否正在使用旧版本的编译器,并且该属性仅在新版本中可用。

unnameable-test-items

unnameable_test_items lint 检测 #[test] 函数,这些函数由于位于不可命名位置而无法被测试 harness 运行。

示例

fn main() {
    #[test]
    fn foo() {
        // This test will not fail because it does not run.
        assert_eq!(1, 2);
    }
}

这将产生

warning: cannot test inner items
 --> lint_example.rs:2:5
  |
2 |     #[test]
  |     ^^^^^^^
  |
  = note: `#[warn(unnameable_test_items)]` on by default
  = note: this warning originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

解释

为了使测试 harness 运行测试,测试函数必须位于可以从 crate 根访问的位置。这通常意味着它必须在模块中定义,而不是在其他任何地方,例如在另一个函数内部。编译器以前允许这样做而没有错误,因此添加了一个 lint 作为警报,表明测试未使用。是否应该允许这样做尚未决定,请参阅 RFC 2471 和 issue #36629

unpredictable-function-pointer-comparisons

unpredictable_function_pointer_comparisons lint 检查以函数指针作为操作数的比较。

示例

fn a() {}
fn b() {}

let f: fn() = a;
let g: fn() = b;

let _ = f == g;

这将产生

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
 --> lint_example.rs:8:9
  |
8 | let _ = f == g;
  |         ^^^^^^
  |
  = note: the address of the same function can vary between different codegen units
  = note: furthermore, different functions could have the same address after being merged together
  = note: for more information visit <https://doc.rust-lang.net.cn/nightly/core/ptr/fn.fn_addr_eq.html>
  = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
  |
8 | let _ = std::ptr::fn_addr_eq(f, g);
  |         +++++++++++++++++++++ ~  +

解释

函数指针比较不会产生有意义的结果,因为它们永远不能保证是唯一的,并且可能在不同的代码生成单元之间有所不同。此外,不同的函数在合并后可能具有相同的地址。

unreachable-code

unreachable_code lint 检测不可达的代码路径。

示例

panic!("we never go past here!");

let x = 5;

这将产生

warning: unreachable statement
 --> lint_example.rs:4:1
  |
2 | panic!("we never go past here!");
  | -------------------------------- any code following this expression is unreachable
3 |
4 | let x = 5;
  | ^^^^^^^^^^ unreachable statement
  |
  = note: `#[warn(unreachable_code)]` on by default

解释

不可达的代码可能表示错误或未完成的代码。如果代码不再使用,请考虑删除它。

unreachable-patterns

unreachable_patterns lint 检测不可达的模式。

示例

let x = 5;
match x {
    y => (),
    5 => (),
}

这将产生

warning: unreachable pattern
 --> lint_example.rs:5:5
  |
4 |     y => (),
  |     - matches any value
5 |     5 => (),
  |     ^ no value can reach this
  |
  = note: `#[warn(unreachable_patterns)]` on by default

解释

这通常表明模式的指定或排序方式有误。在此示例中,y 模式将始终匹配,因此 five 是不可能达到的。请记住,match 分支按顺序匹配,您可能想要将 5 分支放在 y 分支之上。

unstable-name-collision

lint unstable-name-collision 已重命名为 unstable-name-collisions

unstable-name-collisions

unstable_name_collisions lint 检测到您使用了标准库计划在将来添加的名称。

示例

trait MyIterator : Iterator {
    // is_partitioned is an unstable method that already exists on the Iterator trait
    fn is_partitioned<P>(self, predicate: P) -> bool
    where
        Self: Sized,
        P: FnMut(Self::Item) -> bool,
    {true}
}

impl<T: ?Sized> MyIterator for T where T: Iterator { }

let x = vec![1, 2, 3];
let _ = x.iter().is_partitioned(|_| true);

这将产生

warning: a method with this name may be added to the standard library in the future
  --> lint_example.rs:14:18
   |
14 | let _ = x.iter().is_partitioned(|_| true);
   |                  ^^^^^^^^^^^^^^
   |
   = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
   = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
   = help: call with fully qualified syntax `MyIterator::is_partitioned(...)` to keep using the current method
   = note: `#[warn(unstable_name_collisions)]` on by default
help: add `#![feature(iter_is_partitioned)]` to the crate attributes to enable `is_partitioned`
   |
1  + #![feature(iter_is_partitioned)]
   |

解释

当新方法被添加到标准库的 traits 中时,它们通常以 “不稳定” 的形式添加,这种形式仅在 nightly channel 上通过 feature 属性 可用。 如果存在任何预先存在的代码扩展了一个 trait 以拥有一个同名的方法,那么名称将会冲突。 在未来,当该方法稳定后,这将由于歧义而导致错误。 此 lint 是一种提前警告,让您知道未来可能存在冲突。 这可以通过添加类型注解来消除歧义,以明确您打算调用哪个 trait 方法来避免,例如 MyIterator::is_partitioned(my_iter, my_predicate),或者重命名或删除该方法。

unstable-syntax-pre-expansion

unstable_syntax_pre_expansion lint 检测在属性展开期间被丢弃的不稳定语法的使用。

示例

#[cfg(FALSE)]
macro foo() {}

这将产生

warning: `macro` is experimental
 --> lint_example.rs:3:1
  |
3 | macro foo() {}
  | ^^^^^^^^^^^^^^
  |
  = note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
  = help: add `#![feature(decl_macro)]` to the crate attributes to enable
  = note: this compiler was built on 2025-02-17; consider upgrading it if it is out of date
  = warning: unstable syntax can change at any point in the future, causing a hard error!
  = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>

解释

活动属性(例如 #[cfg] 或过程宏属性)的输入必须是有效的语法。 以前,编译器仅在解析 #[cfg] gates 和展开过程宏之后才限制不稳定语法特性的使用。

为了避免依赖不稳定语法,请将不稳定语法的用法移动到编译器不解析该语法的位置,例如类函数宏。

#![deny(unstable_syntax_pre_expansion)]

macro_rules! identity {
   ( $($tokens:tt)* ) => { $($tokens)* }
}

#[cfg(FALSE)]
identity! {
   macro foo() {}
}

这是一个 未来不兼容的 lint,以便将来过渡到硬错误。 有关更多详细信息,请参阅 issue #65860

unsupported-fn-ptr-calling-conventions

每当在不支持函数指针上调用约定的目标上使用目标依赖的调用约定时,就会输出 unsupported_fn_ptr_calling_conventions lint。

例如,stdcall 对于 x86_64 或更明显的 powerpc 代码来说没有多大意义,因为从未为这些目标指定此调用约定。

示例

fn stdcall_ptr(f: extern "stdcall" fn ()) {
    f()
}

这将产生

warning: the calling convention `"stdcall"` is not supported on this target
  --> $DIR/unsupported.rs:34:15
   |
LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
   |               ^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260>
   = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default

解释

在大多数目标上,stdcall 和类似的调用约定的行为根本没有定义,但由于编译器实现中的错误,以前被接受。

unused-doc-comment

lint unused-doc-comment 已重命名为 unused-doc-comments

unused-tuple-struct-fields

lint unused-tuple-struct-fields 已重命名为 dead-code

unused-allocation

unused_allocation lint 检测可以消除的不必要的分配。

示例

fn main() {
    let a = Box::new([1, 2, 3]).len();
}

这将产生

warning: unnecessary allocation, use `&` instead
 --> lint_example.rs:2:13
  |
2 |     let a = Box::new([1, 2, 3]).len();
  |             ^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_allocation)]` on by default

解释

box 表达式立即被强制转换为引用时,则分配是不必要的,应该使用引用(使用 &&mut)来代替,以避免分配。

unused-assignments

unused_assignments lint 检测永远不会被读取的赋值。

示例

let mut x = 5;
x = 6;

这将产生

warning: value assigned to `x` is never read
 --> lint_example.rs:3:1
  |
3 | x = 6;
  | ^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` on by default

解释

未使用的赋值可能表示错误或未完成的代码。 如果变量在赋值后从未使用过,则可以删除该赋值。 带有下划线前缀的变量(例如 _x)不会触发此 lint。

unused-associated-type-bounds

当关联类型边界被添加到 trait 对象时,但该关联类型具有 where Self: Sized 边界,因此无论如何都无法在 trait 对象上使用时,会发出 unused_associated_type_bounds lint。

示例

trait Foo {
    type Bar where Self: Sized;
}
type Mop = dyn Foo<Bar = ()>;

这将产生

warning: unnecessary associated type bound for dyn-incompatible associated type
 --> lint_example.rs:5:20
  |
5 | type Mop = dyn Foo<Bar = ()>;
  |                    ^^^^^^^^ help: remove this bound
  |
  = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`
  = note: `#[warn(unused_associated_type_bounds)]` on by default

解释

就像带有 Self: Sized 边界的方法在 trait 对象上不可用一样,关联类型也可以从 trait 对象中删除。

unused-attributes

unused_attributes lint 检测编译器未使用的属性。

示例

#![ignore]

这将产生

warning: `#[ignore]` only has an effect on functions
 --> lint_example.rs:1:1
  |
1 | #![ignore]
  | ^^^^^^^^^^
  |
  = note: `#[warn(unused_attributes)]` on by default

解释

未使用的 属性 可能表示该属性放置的位置不正确。 考虑删除它,或将其放置在正确的位置。 还要考虑您是否打算使用内部属性(带有 !,例如 #![allow(unused)]),它应用于属性所在的项,或者外部属性(没有 !,例如 #[allow(unused)]),它应用于跟随属性的项。

unused-braces

unused_braces lint 检测表达式周围不必要的大括号。

示例

if { true } {
    // ...
}

这将产生

warning: unnecessary braces around `if` condition
 --> lint_example.rs:2:4
  |
2 | if { true } {
  |    ^^    ^^
  |
  = note: `#[warn(unused_braces)]` on by default
help: remove these braces
  |
2 - if { true } {
2 + if true {
  |

解释

不需要大括号,应该删除。 这是编写这些表达式的首选风格。

unused-comparisons

unused_comparisons lint 检测由于涉及类型的限制而变得无用的比较。

示例

fn foo(x: u8) {
    x >= 0;
}

这将产生

warning: comparison is useless due to type limits
 --> lint_example.rs:3:5
  |
3 |     x >= 0;
  |     ^^^^^^
  |
  = note: `#[warn(unused_comparisons)]` on by default

解释

无用的比较可能表示错误,应修复或删除。

unused-doc-comments

unused_doc_comments lint 检测 rustdoc 未使用的文档注释。

示例

/// docs for x
let x = 12;

这将产生

warning: unused doc comment
 --> lint_example.rs:2:1
  |
2 | /// docs for x
  | ^^^^^^^^^^^^^^
3 | let x = 12;
  | ----------- rustdoc does not generate documentation for statements
  |
  = help: use `//` for a plain comment
  = note: `#[warn(unused_doc_comments)]` on by default

解释

rustdoc 并非在所有位置都使用文档注释,因此文档注释将被忽略。 尝试将其更改为带有 // 的普通注释以避免警告。

unused-features

unused_features lint 检测在 crate 级别的 feature 属性 中找到的未使用或未知的 feature。

注意:此 lint 目前不可用,有关更多详细信息,请参阅 issue #44232

unused-imports

unused_imports lint 检测从未使用过的导入。

示例

use std::collections::HashMap;

这将产生

warning: unused import: `std::collections::HashMap`
 --> lint_example.rs:2:5
  |
2 | use std::collections::HashMap;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

解释

未使用的导入可能表示错误或未完成的代码,并且会使代码混乱,应将其删除。 如果您打算重新导出该项以使其在模块外部可用,请添加可见性修饰符,例如 pub

unused-labels

unused_labels lint 检测从未使用过的 labels

示例

'unused_label: loop {}

这将产生

warning: unused label
 --> lint_example.rs:2:1
  |
2 | 'unused_label: loop {}
  | ^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_labels)]` on by default

解释

未使用的 label 可能表示错误或未完成的代码。 要静音单个 label 的警告,请在其前面加上下划线,例如 '_my_label:

unused-macros

unused_macros lint 检测未使用的宏。

请注意,此 lint 与 unused_macro_rules lint 不同,后者检查从未使用过的宏的单个规则,因此永远不会展开。

示例

macro_rules! unused {
    () => {};
}

fn main() {
}

这将产生

warning: unused macro definition: `unused`
 --> lint_example.rs:1:14
  |
1 | macro_rules! unused {
  |              ^^^^^^
  |
  = note: `#[warn(unused_macros)]` on by default

解释

未使用的宏可能表示错误或未完成的代码。 要静音单个宏的警告,请在名称前加上下划线,例如 _my_macro。 如果您打算导出宏以使其在 crate 外部可用,请使用 macro_export 属性

unused-must-use

unused_must_use lint 检测标记为 #[must_use] 类型的未使用的结果。

示例

fn returns_result() -> Result<(), ()> {
    Ok(())
}

fn main() {
    returns_result();
}

这将产生

warning: unused `Result` that must be used
 --> lint_example.rs:6:5
  |
6 |     returns_result();
  |     ^^^^^^^^^^^^^^^^
  |
  = note: this `Result` may be an `Err` variant, which should be handled
  = note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
  |
6 |     let _ = returns_result();
  |     +++++++

解释

#[must_use] 属性指示忽略该值是一个错误。 有关更多详细信息,请参阅 参考

unused-mut

unused_mut lint 检测不需要是可变的 mut 变量。

示例

let mut x = 5;

这将产生

warning: variable does not need to be mutable
 --> lint_example.rs:2:5
  |
2 | let mut x = 5;
  |     ----^
  |     |
  |     help: remove this `mut`
  |
  = note: `#[warn(unused_mut)]` on by default

解释

首选风格是仅在需要时才将变量标记为 mut

unused-parens

unused_parens lint 检测带有括号的 ifmatchwhilereturn; 它们不需要括号。

示例

if(true) {}

这将产生

warning: unnecessary parentheses around `if` condition
 --> lint_example.rs:2:3
  |
2 | if(true) {}
  |   ^    ^
  |
  = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
  |
2 - if(true) {}
2 + if true {}
  |

解释

不需要括号,应该删除。 这是编写这些表达式的首选风格。

unused-unsafe

unused_unsafe lint 检测不必要的 unsafe 块的使用。

示例

unsafe {}

这将产生

warning: unnecessary `unsafe` block
 --> lint_example.rs:2:1
  |
2 | unsafe {}
  | ^^^^^^ unnecessary `unsafe` block
  |
  = note: `#[warn(unused_unsafe)]` on by default

解释

如果块中的任何内容都不需要 unsafe,则删除 unsafe 标记,因为它不是必需的,并且可能会引起混淆。

unused-variables

unused_variables lint 检测未以任何方式使用的变量。

示例

let x = 5;

这将产生

warning: unused variable: `x`
 --> lint_example.rs:2:5
  |
2 | let x = 5;
  |     ^ help: if this is intentional, prefix it with an underscore: `_x`
  |
  = note: `#[warn(unused_variables)]` on by default

解释

未使用的变量可能表示错误或未完成的代码。 要静音单个变量的警告,请在其前面加上下划线,例如 _x

useless-ptr-null-checks

useless_ptr_null_checks lint 检查针对从非空类型获得的指针进行的无用的空值检查。

示例

fn test() {}
let fn_ptr: fn() = /* somehow obtained nullable function pointer */
  test;

if (fn_ptr as *const ()).is_null() { /* ... */ }

这将产生

warning: function pointers are not nullable, so checking them for null will always return false
 --> lint_example.rs:6:4
  |
6 | if (fn_ptr as *const ()).is_null() { /* ... */ }
  |    ^------^^^^^^^^^^^^^^^^^^^^^^^^
  |     |
  |     expression has type `fn()`
  |
  = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
  = note: `#[warn(useless_ptr_null_checks)]` on by default

解释

函数指针和引用被假定为非空,检查它们是否为空将始终返回 false。

warnings

warnings lint 允许您更改其他产生警告的 lint 的级别。

示例

#![deny(warnings)]
fn foo() {}

这将产生

error: function `foo` is never used
 --> lint_example.rs:3:4
  |
3 | fn foo() {}
  |    ^^^
  |
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(warnings)]
  |         ^^^^^^^^
  = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`

解释

warnings lint 有点特殊; 通过更改其级别,您可以将每个其他会产生警告的警告更改为您想要的任何值。 因此,您永远不会在代码中直接触发此 lint。

while-true

while_true lint 检测 while true { }

示例

while true {

}

这将产生

warning: denote infinite loops with `loop { ... }`
 --> lint_example.rs:2:1
  |
2 | while true {
  | ^^^^^^^^^^ help: use `loop`
  |
  = note: `#[warn(while_true)]` on by default

解释

while true 应替换为 looploop 表达式是编写无限循环的首选方式,因为它更直接地表达了循环的意图。