默认警告 Lint

这些 Lint 默认情况下都设置为 'warn' 级别。

ambiguous-glob-imports

ambiguous_glob_imports Lint 检测应该报告歧义错误的全局导入,但之前由于 rustc 错误而没有这样做。

示例

#![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 检测通过全局重新导出的名称冲突的情况。尝试使用从多个全局重新导出的相同名称的下游用户将收到警告,指出重新定义了相同的名称。

示例

#![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 使得 cargo fix 工具可以使用 --edition 标志自动将旧代码从 2015 版过渡到 2018 版。该工具将运行这个 Lint 并自动应用编译器建议的修复(即为每个参数添加 _)。这提供了一种完全自动化的方式来更新旧代码以适应新版本。有关更多详细信息,请参阅 问题 #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 反糖化为一个普通的 fn,该函数返回一个不透明的 impl Future<..> + Send 类型。

例如,而不是

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

trait 的作者可能希望编写

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

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

相反,如果该 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 建议使用 dyn Trait 来表示 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 an object-safe trait, use `dyn`
  |
4 | fn takes_trait_object(_: Box<dyn Trait>) {
  |                              +++

解释

如果没有 dyn 指示符,在阅读代码时,您是否正在查看 trait 对象可能会模棱两可或令人困惑。dyn 关键字使它变得明确,并增加了与 impl Trait 相比的对称性。

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 表达式会产生硬错误,也可以通过将表达式括在括号中来消除。

byte-slice-in-packed-struct-with-derive

byte_slice_in_packed_struct_with_derive lint 检测在派生一个或多个内置 trait 的 packed 结构体中使用字节切片字段 ([u8]) 或字符串切片字段 (str) 的情况。

示例

#[repr(packed)]
#[derive(Hash)]
struct FlexZeroSlice {
    width: u8,
    data: [u8],
}

这将产生

warning: byte slice in a packed struct that derives a built-in trait
 --> lint_example.rs:6:5
  |
3 | #[derive(Hash)]
  |          ---- in this derive macro expansion
...
6 |     data: [u8],
  |     ^^^^^^^^^^
  |
  = 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 #107457 <https://github.com/rust-lang/rust/issues/107457>
  = help: consider implementing the trait by hand, or remove the `packed` attribute
  = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
  = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)

解释

这以前是可接受的,但现在正在逐步淘汰,因为 packed 结构体中的字段现在需要实现 Copy 才能使 derive 工作。字节切片和字符串切片是一个临时的例外,因为某些 crate 依赖于它们。

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 定义是正确且等效的,并可能考虑将它们统一在一个位置。

此 lint 不会在 crate 之间运行,因为一个项目可能具有依赖项,它们都依赖于相同的外部函数,但以不同的(但有效)方式声明它。例如,它们可能都为一个或多个参数声明了一个不透明类型(最终将成为不同的类型),或者使用在定义 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

解释

过去,编译器会接受对相同函数的 trait 实现,这些实现仅在生命周期绑定器出现的位置不同。由于借用检查器实现的更改以修复几个错误,这不再允许。但是,由于这会影响现有代码,因此这是一个 未来不兼容 的 lint,以便将来将其过渡到硬错误。

依赖于此模式的代码应该引入 "新类型",例如 struct Foo(for<'a> fn(&'a u8))

有关更多详细信息,请参阅 问题 #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-eval-mutable-ptr-in-final-value

const_eval_mutable_ptr_in_final_value lint 检测可变指针是否泄漏到 const 表达式的最终值中。

示例

pub enum JsValue {
    Undefined,
    Object(std::cell::Cell<bool>),
}

impl ::std::ops::Drop for JsValue {
    fn drop(&mut self) {}
}

const UNDEFINED: &JsValue = &JsValue::Undefined;

fn main() {
}

这将产生

warning: encountered mutable pointer in final value of constant
  --> lint_example.rs:10:1
   |
10 | const UNDEFINED: &JsValue = &JsValue::Undefined;
   | ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = 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 #122153 <https://github.com/rust-lang/rust/issues/122153>
   = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default

解释

在 1.77 版本中,const 评估机制采用了一些更严格的规则来拒绝包含可能最终持有对存储在静态内存中的状态的可变引用的值的表达式(本质上是不可变的)。

这是一个 未来不兼容 的 lint,以简化向错误的过渡。有关更多详细信息,请参阅 问题 #122153

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,以便将来将其过渡到硬错误。有关更详细的描述和可能的修复方法,请参阅 问题 #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 没有被修改。每次您按名称引用 const(例如上面的示例中的 FOO)时,该值的单独副本都会在该位置内联。

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

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

  • 首先,始终重新考虑使用可变全局变量,因为它们可能难以正确使用,并且会使代码更难使用或理解。
  • 如果您尝试对全局变量进行一次性初始化
    • 如果该值可以在编译时计算,请考虑使用与 const 兼容的值(请参阅 常量评估)。
    • 对于更复杂的单次初始化情况,请考虑使用第三方 crate,例如 lazy_staticonce_cell
    • 如果您正在使用 nightly 频道,请考虑标准库中的新 lazy 模块。
  • 如果您确实需要可变全局变量,请考虑使用 static,它有各种选项
    • 简单数据类型可以直接定义并使用 atomic 类型进行修改。
    • 更复杂类型可以放置在同步原语中,例如 Mutex,它可以使用上面列出的选项之一进行初始化。
    • 可变的 static 是一个低级原语,需要 unsafe。通常,应该避免使用它,而应优先使用上面列出的更高级别的东西。

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

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_into_dyn_supertrait lint 在使用 Deref 实现时输出,其中 dyn SuperTrait 类型作为 Output

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 上转型强制转换特性添加了新的强制转换规则,优先于某些其他强制转换规则,这将导致一些行为改变。

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:6:27
  |
6 |     let x = ptr::addr_of!(*ptr::null::<i32>());
  |                           ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed


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

解释

即使作为位置表达式,解引用空指针也会导致 未定义行为,例如 &*(0 as *const i32)addr_of!(*(0 as *const i32))

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 的泛型特征边界很可能是误导性的,不是程序员的本意(他们可能应该使用 std::mem::needs_drop 代替)。

Drop 边界实际上并不表示类型是否可以被平凡地丢弃,因为包含 Drop 类型的复合类型并不一定本身实现 Drop。天真地,人们可能倾向于编写一个实现,假设类型可以被平凡地丢弃,同时还为 T: Drop 提供一个专门化,它实际上调用析构函数。但是,当 TString 时,这会失效,String 本身不实现 Drop,但包含一个 Vec,它实现了 Drop,因此假设 T 可以被平凡地丢弃会导致内存泄漏。

此外,Drop 特征只包含一个方法 Drop::drop,它可能不会在用户代码中被显式调用(E0040),因此实际上没有使用 Drop 在特征边界中的用例,除了可能的一些模糊的极端情况,可以使用 #[allow(drop_bounds)]

dropping-copy-types

dropping_copy_types lint 检查对 std::mem::drop 的调用,其中值派生了 Copy 特征。

示例

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: use `let _ = ...` to ignore the expression or result
  = note: `#[warn(dropping_copy_types)]` on by default

解释

调用 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: use `let _ = ...` to ignore the expression or result
  = note: `#[warn(dropping_references)]` on by default

解释

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

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 的特征对象。

示例

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 的特征对象边界很可能是误导性的,不是程序员的本意。

Drop 边界实际上并不表示类型是否可以被平凡地丢弃,因为包含 Drop 类型的复合类型并不一定本身实现 Drop。天真地,人们可能倾向于编写一个延迟丢弃系统,使用 dyn Drop 特征对象将清理内存从延迟敏感的代码路径中拉出来。但是,当 TString 时,这会失效,String 不实现 Drop,但可能应该被接受。

要编写一个接受任何内容的特征对象边界,请使用具有泛型实现的占位符特征。

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

elided-lifetimes-in-associated-constant

elided_lifetimes_in_associated_constant lint 检测在关联常量中被错误地允许的省略生命周期。

示例

#![deny(elided_lifetimes_in_associated_constant)]

struct Foo;

impl Foo {
    const STR: &str = "hello, world";
}

这将产生

error: `&` without an explicit lifetime name cannot be used here
 --> lint_example.rs:7:16
  |
7 |     const STR: &str = "hello, world";
  |                ^
  |
  = 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 #115010 <https://github.com/rust-lang/rust/issues/115010>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(elided_lifetimes_in_associated_constant)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use the `'static` lifetime
  |
7 |     const STR: &'static str = "hello, world";
  |                 +++++++

解释

以前的 Rust 版本

由于歧义,决定 反对 关联常量中的隐式 static-in-const 行为。但是,这却退化了,编译器错误地将关联常量中的省略生命周期视为 impl 上的生命周期参数。

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

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 特征,这允许在 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)]
#![deny(bad_style)]

fn main() {}

这将产生

warning: deny(bad_style) incompatible with previous forbid
 --> lint_example.rs:2:9
  |
1 | #![forbid(warnings)]
  |           -------- `forbid` level set here
2 | #![deny(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)]

解释

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

forgetting-copy-types

forgetting_copy_types lint 检查对 std::mem::forget 的调用,其中值派生了 Copy 特征。

示例

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: use `let _ = ...` to ignore the expression or result
  = note: `#[warn(forgetting_copy_types)]` on by default

解释

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

另一种同样有效的解释是,Copy 类型没有实现 Drop 特性,这意味着它们没有析构函数。如果没有析构函数,std::mem::forget 就没有东西可以忽略。

forgetting-references

forgetting_references 警告检查对 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: use `let _ = ...` to ignore the expression or result
  = note: `#[warn(forgetting_references)]` on by default

解释

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

function-item-references

function_item_references 警告检测使用 fmt::Pointer 或进行类型转换的函数引用。

示例

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

解释

对函数获取引用可能会被误认为是获取该函数的指针的方法。当将引用格式化为指针或进行类型转换时,这可能会产生意外的结果。当函数引用被格式化为指针、作为 fmt::Pointer 绑定的参数传递或进行类型转换时,会发出此警告。

hidden-glob-reexports

hidden_glob_reexports 警告检测全局重新导出项被私有项遮蔽的情况。

示例

#![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 Foodep::inner::Foo 会静默地变得不可访问,并在下游使用站点触发 "struct Foo is private" 可见性错误。

improper-ctypes

improper_ctypes 警告检测在外部模块中类型使用不当的情况。

示例

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 块中使用的类型是否安全,并遵循某些规则以确保与外部接口的正确兼容性。当检测到定义中可能存在错误时,会发出此警告。警告通常会提供有关问题描述的信息,以及可能解决问题的方法提示。

improper-ctypes-definitions

improper_ctypes_definitions 警告检测 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 不兼容。此警告提醒您不应使用这些类型。警告通常会提供有关问题描述的信息,以及可能解决问题的方法提示。

incomplete-features

incomplete_features 警告检测使用 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

解释

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

indirect-structural-match

indirect_structural_match 警告检测在模式中手动实现 PartialEqEqconst

示例

#![deny(indirect_structural_match)]

struct NoDerive(i32);
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
impl Eq for NoDerive { }
#[derive(PartialEq, Eq)]
struct WrapParam<T>(T);
const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
fn main() {
    match WRAP_INDIRECT_PARAM {
        WRAP_INDIRECT_PARAM => { }
        _ => { }
    }
}

这将产生

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
  --> lint_example.rs:11:9
   |
11 |         WRAP_INDIRECT_PARAM => { }
   |         ^^^^^^^^^^^^^^^^^^^
   |
   = 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 #120362 <https://github.com/rust-lang/rust/issues/120362>
   = note: the traits must be derived, manual `impl`s are not sufficient
   = note: see https://doc.rust-lang.net.cn/stable/std/marker/trait.StructuralPartialEq.html for details
note: the lint level is defined here
  --> lint_example.rs:1:9
   |
1  | #![deny(indirect_structural_match)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^

解释

编译器在过去无意中接受了这种形式。这是一个 未来不兼容 的警告,以便在将来将其转换为硬错误。有关问题的完整描述和一些可能的解决方案,请参阅 问题 #62411

inline-no-sanitize

inline_no_sanitize 警告检测 #[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 警告检测使用 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 警告检查对 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

解释

尝试创建这样的 str 将始终返回错误,如 std::str::from_utf8std::str::from_utf8_mut 的文档所述。

invalid-macro-export-arguments

invalid_macro_export_arguments 警告检测 #[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 警告检查将 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 警告检测创建无效值的情况,例如空引用。

示例

#![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

解释

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

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

irrefutable-let-patterns

irrefutable_let_patterns 警告检测 不可反驳的模式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 语句就足够了。但是,在使用宏生成代码时,禁止不可反驳的模式将需要在宏不知道模式是否可反驳的情况下进行笨拙的解决方法。此警告允许宏接受这种形式,同时提醒您在正常代码中可能使用不当。

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

large-assignments

large_assignments 警告检测大型类型对象被移动的情况。

示例

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

解释

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

late-bound-lifetime-arguments

late_bound_lifetime_arguments 警告检测具有晚绑定生命周期参数的路径段中的泛型生命周期参数。

示例

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

解释

如果早绑定生命周期参数与晚绑定参数在同一个列表中混合使用,则不清楚如何为早绑定生命周期参数提供参数。目前,如果存在晚绑定参数,则提供任何显式参数都会触发此警告,因此将来可以采用解决方案而不会遇到向后兼容性问题。这是一个 未来不兼容 的警告,以便在将来将其转换为硬错误。有关更多详细信息以及早绑定参数和晚绑定参数之间差异的描述,请参阅 问题 #42868

legacy-derive-helpers

legacy_derive_helpers 警告检测在引入之前使用的派生助手属性。

示例

#[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(Deserialize)]
#[serde(rename_all = "camelCase")]
struct S { /* fields */ }

map-unit-fn

map_unit_fn 警告检查 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 警告检测不同 脚本 中标识符之间的视觉混淆字符。

示例

// 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

解释

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

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

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

named-arguments-used-positionally

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

示例

#![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 格式字符串可以通过其位置引用命名参数,但这种用法可能令人困惑。特别是,读者可能会错误地认为命名参数的声明是赋值(这将产生单元类型)。为了向后兼容,这不是硬错误。

no-mangle-generic-items

no-mangle-generic-items 警告检测必须被混淆的泛型项。

示例

#[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

警告 non-fmt-panic 已重命名为 non-fmt-panics

non-camel-case-types

non_camel_case_types lint 检测类型、变体、特征和类型参数,这些类型、变体、特征和类型参数没有使用驼峰命名法。

示例

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 检测使用排他性 范围模式 时可能出现的越界错误。

示例

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

这将产生

warning: multiple ranges are one apart
 --> lint_example.rs:5:5
  |
5 |     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`
6 |     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

解释

在匹配表达式中,范围模式遗漏单个数字很可能是错误的。检查开始值和结束值是否符合预期,并记住使用 ..= 时右边界是包含的,而使用 .. 时右边界是排他的。

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!(123) 会以 i32 作为消息引发恐慌。

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

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 检测对无操作方法的特定调用,例如调用 <&T as 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;
  |

解释

某些方法调用是无操作的,这意味着它们什么也不做。通常,这些方法是由于泛型实现导致的,这些泛型实现恰好创建了一些最终什么也不做的方法调用。例如,Clone 在所有 &T 上实现,但对 &T 调用 clone(其中 T 未实现克隆),实际上什么也不做,因为引用是可复制的。此 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
}

这将产生

warning: opaque type `impl Trait<Assoc = Tait>` does not satisfy its associated type bounds
  --> lint_example.rs:18:25
   |
9  |     type Assoc: Duh;
   |                 --- this associated type bound is unsatisfied for `Tait`
...
18 | 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 来修复它。

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

解释

在匹配表达式中,范围模式以这种方式重叠很可能是错误的。检查开始值和结束值是否符合预期,并记住使用 ..= 时左右边界是包含的。

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

解释

通常,没有效果的语句是错误的。

pointer-structural-match

pointer_structural_match lint 检测在模式中使用的指针,这些指针的行为不能在编译器版本和优化级别之间依赖。

示例

#![deny(pointer_structural_match)]
fn foo(a: usize, b: usize) -> usize { a + b }
const FOO: fn(usize, usize) -> usize = foo;
fn main() {
    match FOO {
        FOO => {},
        _ => {},
    }
}

这将产生

error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
 --> lint_example.rs:6:9
  |
6 |         FOO => {},
  |         ^^^
  |
  = 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 #120362 <https://github.com/rust-lang/rust/issues/120362>
note: the lint level is defined here
 --> lint_example.rs:1:9
  |
1 | #![deny(pointer_structural_match)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^

解释

以前版本的 Rust 允许在模式中使用函数指针和所有原始指针。虽然这些在许多情况下按用户预期工作,但由于优化,指针可能“不等于自身”,或者指向不同函数的指针在运行时比较为相等。这是因为 LLVM 优化可以对函数体相同的函数进行重复数据删除,从而也使指向这些函数的指针指向相同的位置。此外,如果函数在不同的板条箱中实例化并且未通过 LTO 再次重复数据删除,则函数可能会被重复。由 const 创建的内存的指针标识同样不可靠。

private-bounds

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

示例

#![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)]
  |         ^^^^^^^^^^^^^^

解释

在项边界中使用私有类型或特征会降低项实际提供的接口的清晰度。

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 是由于忽略了外部板条箱中宏的可见性检查而产生的。

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

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 返回类型,这意味着实现添加了关于返回类型的未在特征中出现的信息。

示例

#![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 签名中编写的类型。这可能是预期的行为,但也可能导致意外地泄露实现细节。特别是,对于不希望对类型做出比特征签名中编写的更强保证的库作者来说,这可能构成 semver 风险。

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

  • refining_impl_trait_reachable,用于在板条箱外部公开可达的细化,以及
  • refining_impl_trait_internal,用于仅在板条箱内部可见的细化。

我们正在寻求对每个 lint 的反馈;有关更多信息,请参见问题 #121718

refining-impl-trait-reachable

refining_impl_trait_reachable lint 检测方法签名中由公开可达的特征实现细化的 impl 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 签名中编写的类型。这可能是预期的行为,但也可能导致意外地泄露实现细节。特别是,对于不希望对类型做出比特征签名中编写的更强保证的库作者来说,这可能构成 semver 风险。

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

  • refining_impl_trait_reachable,用于在板条箱外部公开可达的细化,以及
  • refining_impl_trait_internal,用于仅在板条箱内部可见的细化。

我们正在寻求对每个 lint 的反馈;有关更多信息,请参见问题 #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,用于在将来将其转换为硬错误。有关更多详细信息,请参见 问题 #78586

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 在宏被调用在表达式位置时,会忽略宏体中的尾部分号。然而,这使得语言中分号的处理方式不一致,并且在某些情况下会导致意外的运行时行为(例如,如果宏作者期望一个值被丢弃)。

这是一个 未来不兼容 的 lint,将在未来将其转换为硬错误。有关更多详细信息,请参阅 问题 #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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
  = note: this will be a hard error in the 2024 edition
  = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
  = note: `#[warn(static_mut_refs)]` on by default
help: use `addr_of!` instead to create a raw pointer
  |
6 |         let y = addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
  = note: this will be a hard error in the 2024 edition
  = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
  |
7 |         let ref x = addr_of!(X);
  |                     ~~~~~~~~~~~


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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
  = note: this will be a hard error in the 2024 edition
  = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
  |
8 |         let (x, y) = (addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
  = note: this will be a hard error in the 2024 edition
  = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
  |
8 |         let (x, y) = (&X, addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
  = note: this will be a hard error in the 2024 edition
  = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
  |
9 |         foo(addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: this will be a hard error in the 2024 edition
   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
   |
17 |     let y = addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: this will be a hard error in the 2024 edition
   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
   |
18 |     let ref x = addr_of!(X);
   |                 ~~~~~~~~~~~


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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: this will be a hard error in the 2024 edition
   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
   |
19 |     let (x, y) = (addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: this will be a hard error in the 2024 edition
   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
   |
19 |     let (x, y) = (&X, addr_of!(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 issue #114447 <https://github.com/rust-lang/rust/issues/114447>
   = note: this will be a hard error in the 2024 edition
   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
help: use `addr_of!` instead to create a raw pointer
   |
20 |     foo(addr_of!(X));
   |         ~~~~~~~~~~~

解释

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

此 lint 在 2021 年之前的版本中默认设置为 "warn",在 2024 年将改为硬错误。

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() 仅取消引用双重引用,而不是克隆内部类型,而内部类型应该是预期的结果。

temporary-cstring-as-ptr

temporary_cstring_as_ptr lint 检测获取临时 CString 的内部指针。

示例

#![allow(unused)]
use std::ffi::CString;
let c_str = CString::new("foo").unwrap().as_ptr();

这将产生

warning: getting the inner pointer of a temporary `CString`
 --> lint_example.rs:4:42
  |
4 | let c_str = CString::new("foo").unwrap().as_ptr();
  |             ---------------------------- ^^^^^^ this pointer will be invalid
  |             |
  |             this `CString` 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 `CString` 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(temporary_cstring_as_ptr)]` on by default

解释

CString 的内部指针仅在它指向的 CString 存在时才有效。获取临时 CString 的内部指针允许 CString 在语句结束时被丢弃,因为它在类型系统看来没有被引用。这意味着在语句之外,指针将指向已释放的内存,如果指针稍后被取消引用,会导致未定义的行为。

trivial-bounds

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

示例

#![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

解释

通常你不会写一个你知道总是为真或从不为真的特征边界。但是,当使用宏时,宏可能在生成代码时不知道约束是否成立。目前,编译器不会在约束总是为真的情况下提醒你,并在约束从不为真的情况下生成错误。trivial_bounds 特性将这种情况更改为两种情况下都发出警告,为宏提供更多自由和灵活性来生成代码,同时仍然在编写非宏代码时提供信号,表明某些地方有问题。

有关更多详细信息,请参阅 RFC 2056。此特性目前仅在 nightly 通道上可用,请参阅 跟踪问题 #48214

type-alias-bounds

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

示例

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

这将产生

warning: bounds on generic parameters are not enforced in type aliases
 --> lint_example.rs:2:17
  |
2 | type SendVec<T: Send> = Vec<T>;
  |                 ^^^^
  |
  = note: `#[warn(type_alias_bounds)]` on by default
help: the bound will not be checked when the type alias is used, and should be removed
  |
2 - type SendVec<T: Send> = Vec<T>;
2 + type SendVec<T> = Vec<T>;
  |

解释

类型别名中的特征边界目前被忽略,不应包含它们以避免混淆。这以前是无意中允许的;这在将来可能会成为硬错误。

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 版中将其转换为硬错误。有关更多详细信息,请参阅 问题 #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 表达式。

undefined-naked-function-abi

undefined_naked_function_abi lint 检测没有指定 ABI 或指定 Rust ABI 的裸函数定义。

示例

#![feature(asm_experimental_arch, naked_functions)]

use std::arch::asm;

#[naked]
pub fn default_abi() -> u32 {
    unsafe { asm!("", options(noreturn)); }
}

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

这将产生

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 目前是未定义的。因此,裸函数应该指定非 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

解释

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

已知的条件包括在 --check-cfg 中传递的名称或值,以及编译器中内置的一些知名名称和值。

unfulfilled-lint-expectations

unfulfilled_lint_expectations lint 检测未满足的 lint 触发期望。

示例

#![feature(lint_reasons)]

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

这将产生

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

解释

预计标记的代码会发出 lint。此期望尚未满足。

如果这是预期行为,则可以删除 expect 属性,否则应该调查为什么不再发出预期的 lint。

在极少数情况下,期望可能会在与显示的代码片段中显示的位置不同的位置发出。在大多数情况下,#[expect] 属性在添加到外部作用域时有效。一些 lint 只能在 crate 级别上预期。

RFC 2383 的一部分。进度正在 #54503 中跟踪。

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 2024-06-10; consider upgrading it if it is out of date
  = note: `#[warn(ungated_async_fn_track_caller)]` on by default

解释

该属性必须与 async_fn_track_caller 特性标志 结合使用。否则,#[track_caller] 注释将作为无操作函数。

uninhabited-static

uninhabited_static lint 检测无居民静态。

示例

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

解释

具有无居民类型的静态永远无法初始化,因此无法定义。但是,这可以通过 extern static 来规避,这会导致编译器在以后出现问题,因为编译器假设没有初始化的无居民位置(例如局部变量或静态变量)。这以前是意外允许的,但正在逐步淘汰。

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] 函数,这些函数无法由测试工具运行,因为它们位于无法命名的位置。

示例

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)

解释

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

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 => (),
  |     ^ unreachable pattern
  |
  = note: `#[warn(unreachable_patterns)]` on by default

解释

这通常表明模式的指定或排序方式有误。在此示例中,y 模式将始终匹配,因此无法访问 5。请记住,匹配分支按顺序匹配,你可能希望将 5 案例放在 y 案例之上。

unstable-name-collision

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

unstable-name-collisions

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

示例

trait MyIterator : Iterator {
    // is_sorted is an unstable method that already exists on the Iterator trait
    fn is_sorted(self) -> bool where Self: Sized {true}
}

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

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

这将产生

warning: a method with this name may be added to the standard library in the future
  --> lint_example.rs:10:18
   |
10 | let _ = x.iter().is_sorted();
   |                  ^^^^^^^^^
   |
   = 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_sorted(...)` to keep using the current method
   = note: `#[warn(unstable_name_collisions)]` on by default
help: add `#![feature(is_sorted)]` to the crate attributes to enable `is_sorted`
   |
1  + #![feature(is_sorted)]
   |

解释

当标准库中的特征添加新方法时,它们通常以“非稳定”形式添加,该形式仅在 nightly 通道 上使用 feature 属性 可用。如果存在任何预先存在的代码扩展特征以具有相同名称的方法,则名称将发生冲突。将来,当该方法被稳定后,这将由于歧义而导致错误。此 lint 是一个早期警告,让你知道将来可能发生冲突。这可以通过添加类型注释来避免,以区分你打算调用的特征方法,例如 MyIterator::is_sorted(my_iter),或者重命名或删除该方法。

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 2024-06-10; 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] 门控并扩展过程宏后才限制非稳定语法特性的使用。

为了避免依赖非稳定语法,请将非稳定语法的使用移到编译器不解析语法的某个位置,例如函数式宏。

#![deny(unstable_syntax_pre_expansion)]

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

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

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

unsupported-calling-conventions

当在无法有效支持请求目标的平台上使用stdcallfastcallthiscallvectorcall 调用约定(或其 unwind 变体)时,会输出unsupported_calling_conventions lint。

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

历史上,MSVC 工具链已将除 x86 之外的其他目标回退到常规 C 调用约定,但 Rust 并没有真正看到在更多目标上引入类似 hack 的类似需求。

示例

extern "stdcall" fn stdcall() {}

这将产生

warning: use of calling convention not supported on this target
  --> $DIR/unsupported.rs:39:1
   |
LL | extern "stdcall" fn stdcall() {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(unsupported_calling_conventions)]` on by default
   = 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 ...

解释

在大多数目标上,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

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

示例

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

这将产生

warning: unnecessary associated type bound for not object safe 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. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
  = note: `#[warn(unused_associated_type_bounds)]` on by default

解释

就像具有Self: Sized 边界的方法无法在特征对象上使用一样,也可以从特征对象中删除关联类型。

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 属性中找到的未使用或未知功能。

注意:此 lint 目前不起作用,有关更多详细信息,请参阅问题 #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 检测标签从未使用。

示例

'unused_label: loop {}

这将产生

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

解释

未使用的标签可能表明错误或未完成的代码。要使单个标签的警告静默,请在其前面加上下划线,例如'_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。

wasm-c-abi

wasm_c_abi lint 检测与未来版本的 Rust 不兼容的 crate 依赖项,这些版本将发出符合规范的 C ABI。

示例

#![deny(wasm_c_abi)]

这将产生

error: the following packages contain code that will be rejected by a future version of Rust: wasm-bindgen v0.2.87
  |
note: the lint level is defined here
 --> src/lib.rs:1:9
  |
1 | #![deny(wasm_c_abi)]
  |         ^^^^^^^^^^

解释

Rust 历史上一直发出不符合规范的 C ABI。这会导致其他编译器和 Wasm 目标之间出现不兼容性。在未来版本的 Rust 中,这将得到修复,因此依赖于不符合规范的 C ABI 的依赖项将停止运行。

where-clauses-object-safety

where_clauses_object_safety lint 检测对象安全性where 子句

示例

trait Trait {}

trait X { fn foo(&self) where Self: Trait; }

impl X for () { fn foo(&self) {} }

impl Trait for dyn X {}

// Segfault at opt-level 0, SIGILL otherwise.
pub fn main() { <dyn X as X>::foo(&()); }

这将产生

warning: the trait `X` cannot be made into an object
 --> lint_example.rs:3:14
  |
3 | trait X { fn foo(&self) where Self: Trait; }
  |              ^^^
  |
  = 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 #51443 <https://github.com/rust-lang/rust/issues/51443>
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.net.cn/reference/items/traits.html#object-safety>
 --> lint_example.rs:3:14
  |
3 | trait X { fn foo(&self) where Self: Trait; }
  |       -      ^^^ ...because method `foo` references the `Self` type in its `where` clause
  |       |
  |       this trait cannot be made into an object...
  = help: consider moving `foo` to another trait
  = note: `#[warn(where_clauses_object_safety)]` on by default

解释

编译器以前允许这些不安全的对象边界,这是不正确的。这是一个未来不兼容的lint,将在未来将其转换为硬错误。有关更多详细信息,请参阅问题 #51443

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 表达式是编写无限循环的首选方式,因为它更直接地表达了循环的意图。

writes-through-immutable-pointer

writes_through_immutable_pointer lint 检测通过从共享引用派生的指针进行写入。

示例

#![feature(const_mut_refs)]
const WRITE_AFTER_CAST: () = unsafe {
    let mut x = 0;
    let ptr = &x as *const i32 as *mut i32;
    *ptr = 0;
};

这将产生

warning: writing through a pointer that was derived from a shared (immutable) reference
 --> lint_example.rs:6:5
  |
6 |     *ptr = 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 #X <https://github.com/rust-lang/rust/issues/X>
  = note: `#[warn(writes_through_immutable_pointer)]` on by default

解释

共享引用是不可变的(当没有涉及UnsafeCell 时),通过它们或通过从它们派生的指针进行写入是未定义的行为。编译器最近学会了在编译时评估期间检测这种未定义的行为,并且将来这将引发硬错误。