什么是 rustc?

欢迎来到“rustc 书”!rustc是 Rust 编程语言的编译器,由项目组开发提供。编译器将您的源代码和生产二进制代码,变成一个或可执行文件。

大多数 Rust 程序员都不会直接调用rustc,而是通过Cargo来完成,虽然这一切都只是调用rustc流程!如果你想看看 Cargo 如何调用rustc, 您可以

$ cargo build --verbose

它会打印出每个rustc调用。本书可以帮助您了解每个选项的作用。此外,虽然大多数 Rustaceans 使用 Cargo,但并非所有人都这样做:有时,他们将rustc整合进其他构建系统。本书会提供您需要执行此操作的所有选项的指南。

基本用法

假设你在文件中有一个小小的 hello world 程序,hello.rs

fn main() {
    println!("Hello, world!");
}

要将此源代码转换为可执行文件,您可以使用rustc

$ rustc hello.rs
$ ./hello # 在 *NIX
$ .\hello.exe # 在 Windows

注意,通常我们只在使用rustc时,传递crate 根文件,不是(我们希望编译的)每个文件。例如,如果我们有一个main.rs,看起来像这样:

mod foo;

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

还有一个foo.rs,如下:

pub fn hello() {
    println!("Hello, world!");
}

要编译它,我们将运行此命令:

$ rustc main.rs

没必要告诉rustc关于foo.rs文件; 该mod语句为rusts提供所需的一切。这与您使用 C 编译器的方式不同,在 C 编译器中,您要在每个文件上调用编译器,然后将所有内容链接在一起。换句话说,crate就是一个编译单位,而不是一个特定的模块组。

命令行参数

这里是,rustc能做什么的命令行参数列表。

-h/--help: 帮助下

该标志将打印出rustc的帮助信息。

--cfg:配置编译环境

此标志可以打开或关闭各种#[cfg]设置。

该值可以是单个标识符,也可以是由=分隔两个标识符。

举些例子,--cfg 'verbose'要么--cfg 'feature="serde"'。分别对应#[cfg(verbose)]#[cfg(feature = "serde")]

-L:将目录添加到库搜索路径

要查找外部包时,就传递给此标志的目录,rustc 会搜索。

-l:将生成的包链接到一个原生库

此标志允许您在构建包时,指定一个特定原生库的链接。

--crate-type:编译器要发出的包的类型列表

这指示rustc构建哪种箱子类型。

--crate-name:指定正在构建的包的名称

这告诉rustc,您的箱子名称。

--emit:发出除箱子以外的输出

这个标志可以打印出装配或 LLVM-IR 之类的东西,而不是生成一个箱子。

--print:打印编译器信息

该标志打印出有,关编译器的各种信息。

-g:包含调试信息

-C debuginfo=2同义,更多看这里

-O:优化您的代码

-C opt-level=2同义,更多看这里

-o:输出的文件名

此标志控制,输出的文件名。

--out-dir:用于写入输出的目录

输出包,被写入的目录。

--explain:提供错误消息的详细说明

每个错误,rustc附带一个错误代码;这将打印出给定错误的更详细解释。

--test:构建测试工具

编译这个箱子时,rustc会忽略你的main功能,而不是产生一个测试工具。

--target:选择要构建的目标三元组

控制了哪个生产目标

-W:设置 lint 警告

该标志将设置,应将哪些 lint 设置为警告水平

-A:设置 lint 允许

该标志将设置,应将哪些 lint 设置为允许水平

-D:设置 lint 拒绝

该标志将设置,应将哪些 lint 设置为拒绝等级

-F:设置 lint 禁止

该标志将设置,应将哪些 lint 设置为禁止等级

--cap-lints:设置最严格的 lint 级别

这个标志让你’盖’lints,更多,看这里

-C/--codegen:代码生成选项

此标志将允许您,设置codegen 选项

-V/--version:打印版本

此标志将打印出来rustc的版本。

-v/--verbose:使用详细输出

该标志与其他标志组合使用时,会产生额外的输出。

--extern:指定外部库的位置

此标志允许您传递外部箱子的位置和名称,并链接该箱到您正在构建的箱子中。

--sysroot:覆盖系统根目录

“sysroot”就是rustc寻找 Rust安装附带的箱子;这个标志允许被覆盖。

--error-format:控制错误的产生方式

此标志允许您控制错误的格式。

--color:配置输出的着色

此标志可让您控制输出的颜色设置。

Lint

在软件中,“lint”是用于帮助改进源代码的工具。Rust 编译器包含许多 lints,当它编译你的代码时,它也会运行 lints。根据您配置的方式,这些 lint 可能会产生警告,错误或根本没有任何内容。

这是一个小例子:

$ cat main.rs
fn main() {
    let x = 5;
}
$ rustc main.rs
warning: unused variable: `x`
 --> main.rs:2:9
  |
2 |     let x = 5;
  |         ^
  |
  = note: #[warn(unused_variables)] on by default
  = note: to avoid this warning, consider using `_x` instead

这是unused_variableslint,它告诉你,你已经引入了一个你不在代码中使用的变量。注意warning: unused variable:x``不是错误,所以这不是错误,但它可能是一个 bug,所以你得到一个警告。

Lint 等级

rustc,lints 分为四个等级

  1. 允许(allow)
  2. 警告(warn)
  3. 拒绝(deny)
  4. 禁止(forbid)

每个 lint 都有一个默认级别(在本章后面的 lint 列表中进行了解释),并且编译器具有默认警告级别。首先,让我们解释这些级别的含义,然后再讨论配置。

允许

存在这些 lint,但默认情况下不执行任何操作。例如,请考虑以下源代码:


# #![allow(unused_variables)]
#fn main() {
pub fn foo() {}
#}

编译此文件不会产生警告:

$ rustc lib.rs --crate-type=lib
$

但是这段代码违反了missing_docslint(缺乏说明文档)。

这些 lint 主要由配置手动打开,我们将在本节后面讨论。

警告

如果您违反“警告”等级的 lint,将发出警告。例如,这段代码与unused_variablelint 相违背:


# #![allow(unused_variables)]
#fn main() {
pub fn foo() {
    let x = 5;
}
#}

这将产生此警告:

$ rustc lib.rs --crate-type=lib
warning: unused variable: `x`
 --> lib.rs:2:9
  |
2 |     let x = 5;
  |         ^
  |
  = note: #[warn(unused_variables)] on by default
  = note: to avoid this warning, consider using `_x` instead

拒绝

如果您违反“拒绝”等级的 lint,将发出错误。例如,此代码违背exceeding_bitshiftslint。

fn main() {
    100u8 << 10;
}
$ rustc main.rs
error: bitshift exceeds the type's number of bits
 --> main.rs:2:13
  |
2 |     100u8 << 10;
  |     ^^^^^^^^^^^
  |
  = note: #[deny(exceeding_bitshifts)] on by default

lint 的错误和常规的传统错误有什么区别?Lints 可以通过级别进行配置,因此像“允许”lints 的方式,能让默认情况下“拒绝”的警告不再出现。同样,您若希望设置,让一个默认情况下warnlint 能产生错误。那 lint 等级能帮到你。

禁止

‘禁止’是一种比’拒绝’更强的特殊 lint 等级。它与’deny’相同,因为此级别的 lint 会产生错误,但与’deny’级别不同,’禁止’级别不能被低于一个错误的信息所覆盖。但是,lint 等级仍可能受到--cap-lints限制(见下文),所以rustc --cap-lints warn将把 ‘禁止’lints 设置为警告。

配置警告级别

记住我们的missing_docs,来自“允许”lint 级别的示例?

$ cat lib.rs
pub fn foo() {}
$ rustc lib.rs --crate-type=lib
$

我们可以配置这个 lint ,升到更高的级别。可用编译器命令行标志,源代码中的属性也行。

您还可以“cap”lints,以便编译器可以选择忽略某些 lint 级别。我们最后再谈。

通过编译器标志

这个-A-W-D,和-F标志,允许您将一个或多个 lints 转换为允许、警告、拒绝或禁止级别,如下所示:

$ rustc lib.rs --crate-type=lib -W missing-docs
warning: missing documentation for crate
 --> lib.rs:1:1
  |
1 | pub fn foo() {}
  | ^^^^^^^^^^^^
  |
  = note: requested on the command line with `-W missing-docs`

warning: missing documentation for a function
 --> lib.rs:1:1
  |
1 | pub fn foo() {}
  | ^^^^^^^^^^^^
$ rustc lib.rs --crate-type=lib -D missing-docs
error: missing documentation for crate
 --> lib.rs:1:1
  |
1 | pub fn foo() {}
  | ^^^^^^^^^^^^
  |
  = note: requested on the command line with `-D missing-docs`

error: missing documentation for a function
 --> lib.rs:1:1
  |
1 | pub fn foo() {}
  | ^^^^^^^^^^^^

error: aborting due to 2 previous errors

还可以多次传递每个标志,以更改多个 lints:

$ rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables

当然,您可以将这四个标志混合在一起:

$ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables

通过属性

您还可以使用箱的宽度属性,修改 lints 级别:

$ cat lib.rs
#![warn(missing_docs)]

pub fn foo() {}
$ rustc lib.rs --crate-type=lib
warning: missing documentation for crate
 --> lib.rs:1:1
  |
1 | / #![warn(missing_docs)]
2 | |
3 | | pub fn foo() {}
  | |_______________^
  |
note: lint level defined here
 --> lib.rs:1:9
  |
1 | #![warn(missing_docs)]
  |         ^^^^^^^^^^^^

warning: missing documentation for a function
 --> lib.rs:3:1
  |
3 | pub fn foo() {}
  | ^^^^^^^^^^^^

全部四个,warnallowdeny,和forbid都是这样工作的。

您还可以为每个属性,传递多个 lints:


# #![allow(unused_variables)]
#![warn(missing_docs, unused_variables)]

#fn main() {
pub fn foo() {}
#}

同时使用多个属性:


# #![allow(unused_variables)]
#![warn(missing_docs)]
#![deny(unused_variables)]

#fn main() {
pub fn foo() {}
#}

Capping lint

rustc支持一种标志,就是--cap-lints LEVEL,它设置“lint 天花板等级”。这是对所有 lint 的最大控制。例如,如果我们从上面的“拒绝”lint 级别,获取代码示例:

fn main() {
    100u8 << 10;
}

我们编译它,以 lint 警告等级作为天花板(封顶):

$ rustc lib.rs --cap-lints warn
warning: bitshift exceeds the type's number of bits
 --> lib.rs:2:5
  |
2 |     100u8 << 10;
  |     ^^^^^^^^^^^
  |
  = note: #[warn(exceeding_bitshifts)] on by default

warning: this expression will panic at run-time
 --> lib.rs:2:5
  |
2 |     100u8 << 10;
  |     ^^^^^^^^^^^ attempt to shift left with overflow

它现在只发出警告,而不是错误。我们可以走得更远,允许所有的 lints:

以‘允许’级别作为天花板,但允许级别默认不输出信息,整洁界面。

$ rustc lib.rs --cap-lints allow
$

这个功能被 Cargo 大量使用;在编译依赖项时,传递--cap-lints allow,这样如果它们有任何警告,它们就不会污染构建的输出。

Lint 组

rustc具有“lint 组”的概念,您可以通过一个名称切换多个警告。

例如,nonstandard-stylelint 一次设置 non-camel-case-typesnon-snake-case,和non-upper-case-globals全部。所以下面命令行是等价的:

$ rustc -D nonstandard-style
$ rustc -D non-camel-case-types -D non-snake-case -D non-upper-case-globals

这是每个 lint 组的列表,以及它们由以下组成的 lint:

描述 lints
nonstandard-style 违反标准命名约定 non-camel-case-types, non-snake-case, non-upper-case-globals
warnings 所有会发出警告的 lints 所有会发出警告的 lints
edition-2018 在 2018 Rust 时变为错误的 lints tyvar-behind-raw-pointer
rust-2018-idioms 倾向 Rust 2018 的惯用功能的 lints bare-trait-object, unreachable-pub
unused 这些 lints 检测到声明但未使用的东西 unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comment, unused-extern-crates, unused-features, unused-parens
future-incompatible 检测具有功能兼容性问题的代码的 lints private-in-public, pub-use-of-private-extern-crate, patterns-in-fns-without-body, safe-extern-statics, invalid-type-param-default, legacy-directory-ownership, legacy-imports, legacy-constructor-visibility, missing-fragment-specifier, illegal-floating-point-literal-pattern, anonymous-parameters, parenthesized-params-in-types-and-modules, late-bound-lifetime-arguments, safe-packed-borrows, incoherent-fundamental-impls, tyvar-behind-raw-pointer, unstable-name-collision

此外,还有一个bad-style组 lint,它是不推荐使用的nonstandard-style别名。

最后,您还可以通过调用rustc -W help。 给出已安装特有版本编译器的确切值。

Lint 列表

此部分列出了所有 lint,按其默认的 lint 级别分组。

您还可以通过运行rustc -W help,查看此列表。

默认允许的 lints

默认情况下,这些 lint 都设置为’allow’级别。因此,除非您使用标志或属性将它们设置为更高的 lint 级别,否则它们将不会显示。

anonymous-parameters

此 lint 检测匿名参数。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
trait Foo {
    fn foo(usize);
}
#}

当设置为’deny’时,这将产生:

error: use of deprecated anonymous parameter
 --> src/lib.rs:5:11
  |
5 |     fn foo(usize);
  |           ^
  |
  = 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 #41686 <https://github.com/rust-lang/rust/issues/41686>

这种语法大多是历史意外,可以很容易地解决:


# #![allow(unused_variables)]
#fn main() {
trait Foo {
    fn foo(_: usize);
}
#}

bare-trait-object

这个 lint 暗示对 trait 对象,使用dyn Trait。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#![feature(dyn_trait)]

#fn main() {
trait Trait { }

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

当设置为’deny’时,这将产生:

error: trait objects without an explicit `dyn` are deprecated
 --> src/lib.rs:7:30
  |
7 | fn takes_trait_object(_: Box<Trait>) {
  |                              ^^^^^ help: use `dyn`: `dyn Trait`
  |

要解决此问题,请按照帮助消息的建议执行操作:


# #![allow(unused_variables)]
#![feature(dyn_trait)]
#![deny(bare_trait_objects)]

#fn main() {
trait Trait { }

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

box-pointers

给 Box 类型使用的 lints。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
struct Foo {
    x: Box<isize>,
}
#}

当设置为’deny’时,这将产生:

error: type uses owned (Box type) pointers: std::boxed::Box<isize>
 --> src/lib.rs:6:5
  |
6 |     x: Box<isize> //~ ERROR type uses owned
  |     ^^^^^^^^^^^^^
  |

这种 lint 主要是历史性的,并不是特别有用。以前,Box<T>是用于构建语言,以及进行堆分配的唯一方法。今天的 Rust 可以调用其他分配器等。

elided-lifetime-in-path

此 lint 检测隐藏生命周期参数的使用。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
struct Foo<'a> {
    x: &'a u32
}

fn foo(x: &Foo) {
}
#}

当设置为’deny’时,这将产生:

error: hidden lifetime parameters are deprecated, try `Foo<'_>`
 --> src/lib.rs:5:12
  |
5 | fn foo(x: &Foo) {
  |            ^^^
  |

生命周期省略规则隐藏这个生命周期,但是这个被弃用了。

missing-copy-implementations

这个 lint 检测到可能被遗忘的Copy实现。一些触发此 lint 的示例代码:


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

当设置为’deny’时,这将产生:

error: type could implement `Copy`; consider adding `impl Copy`
 --> src/main.rs:3:1
  |
3 | / pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy`
4 | |     pub field: i32
5 | | }
  | |_^
  |

您可以通过派生Copy,来修复 lint。

这个 lint 被设置为’allow’,因为这个代码并不坏; 特别是常写一个类似这样的新类型,所以一个Copy类型不再是Copy(it’s common to write newtypes like this specifically so that a Copy type is no longer Copy)。

missing-debug-implementations

此 lint 检测到缺少的fmt::Debug实现。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
pub struct Foo;
#}

当设置为’deny’时,这将产生:

error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
 --> src/main.rs:3:1
  |
3 | pub struct Foo;
  | ^^^^^^^^^^^^^^^
  |

您可以通过派生Debug来修复 lint。

missing-docs

此 lint 检测到公有项的缺乏文档。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
pub fn foo() {}
#}

当设置为’deny’时,这将产生:

error: missing documentation for crate
 --> src/main.rs:1:1
  |
1 | / #![deny(missing_docs)]
2 | |
3 | | pub fn foo() {}
4 | |
5 | | fn main() {}
  | |____________^
  |

error: missing documentation for a function
 --> src/main.rs:3:1
  |
3 | pub fn foo() {}
  | ^^^^^^^^^^^^

要修复 lint,请为所有项添加文档。

single-use-lifetime

此 lint 检测仅使用一次的生命周期。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
struct Foo<'x> {
    x: &'x u32
}
#}

当设置为’deny’时,这将产生:

error: lifetime name `'x` only used once
 --> src/main.rs:3:12
  |
3 | struct Foo<'x> {
  |            ^^
  |

trivial-casts

这种 lint 可以检测到可以移除的琐碎成本。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x: &u32 = &42;
let _ = x as *const u32;
#}

当设置为’deny’时,这将产生:

error: trivial cast: `&u32` as `*const u32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
 --> src/main.rs:5:13
  |
5 |     let _ = x as *const u32;
  |             ^^^^^^^^^^^^^^^
  |
note: lint level defined here
 --> src/main.rs:1:9
  |
1 | #![deny(trivial_casts)]
  |         ^^^^^^^^^^^^^

trivial-numeric-casts

此 lint 检测可以删除的数字类型的简单转换。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x = 42i32 as i32;
#}

当设置为’deny’时,这将产生:

error: trivial numeric cast: `i32` as `i32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
 --> src/main.rs:4:13
  |
4 |     let x = 42i32 as i32;
  |             ^^^^^^^^^^^^
  |

unreachable-pub

这个 lint 无法从箱子根触发了到达的pub项。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
mod foo {
    pub mod bar {

    }
}
#}

当设置为’deny’时,这将产生:

error: unreachable `pub` item
 --> src/main.rs:4:5
  |
4 |     pub mod bar {
  |     ---^^^^^^^^
  |     |
  |     help: consider restricting its visibility: `pub(crate)`
  |

unsafe-code

这种 lint 可以使用unsafe码。一些触发此 lint 的示例代码:

fn main() {
    unsafe {

    }
}

当设置为’deny’时,这将产生:

error: usage of an `unsafe` block
 --> src/main.rs:4:5
  |
4 | /     unsafe {
5 | |
6 | |     }
  | |_____^
  |

unstable-features

此 lint 已弃用,不再使用。

unused-extern-crates

这种 lint 可以防止extern crate,从未使用过的箱。一些触发此 lint 的示例代码:

extern crate semver;

当设置为’deny’时,这将产生:

error: unused extern crate
 --> src/main.rs:3:1
  |
3 | extern crate semver;
  | ^^^^^^^^^^^^^^^^^^^^
  |

unused-import-braces

此 lint 捕获导入项目周围,有不必要的括号。一些触发此 lint 的示例代码:

use test::{A};

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

当设置为’deny’时,这将产生:

error: braces around A is unnecessary
 --> src/main.rs:3:1
  |
3 | use test::{A};
  | ^^^^^^^^^^^^^^
  |

要解决这个问题,use test::A;

unused-qualifications

此 lint 检测到不必要的限定名称。一些触发此 lint 的示例代码:

mod foo {
    pub fn bar() {}
}

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

当设置为’deny’时,这将产生:

error: unnecessary qualification
 --> src/main.rs:9:5
  |
9 |     foo::bar();
  |     ^^^^^^^^
  |

你可以直接调用bar(),没有foo::

unused-results

此 lint 检查语句中表达式的未使用结果。一些触发此 lint 的示例代码:

fn foo<T>() -> T { panic!() }

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

当设置为’deny’时,这将产生:

error: unused result
 --> src/main.rs:6:5
  |
6 |     foo::<usize>();
  |     ^^^^^^^^^^^^^^^
  |

variant-size-differences

此 lint 检测具有各种变体大小的枚举。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
enum En {
    V0(u8),
    VBig([u8; 1024]),
}
#}

当设置为’deny’时,这将产生:

error: enum variant is more than three times larger (1024 bytes) than the next largest
 --> src/main.rs:5:5
  |
5 |     VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
  |     ^^^^^^^^^^^^^^^^
  |

默认警告

默认情况下,这些 lint 都设置为“警告”级别。

const-err

该 lint 在进行持续求值时,检测到一个错误的表达。一些触发此 lint 的示例代码:

let b = 200u8 + 200u8;

这将产生:

warning: attempt to add with overflow
 --> src/main.rs:2:9
  |
2 | let b = 200u8 + 200u8;
  |         ^^^^^^^^^^^^^
  |

dead-code

此 lint 检测未使用的,未导出的项。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
fn foo() {}
#}

这将产生:

warning: function is never used: `foo`
 --> src/lib.rs:2:1
  |
2 | fn foo() {}
  | ^^^^^^^^
  |

deprecated

此 lint 检测使用已弃用的项目。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
#[deprecated]
fn foo() {}

fn bar() {
    foo();
}
#}

这将产生:

warning: use of deprecated item 'foo'
 --> src/lib.rs:7:5
  |
7 |     foo();
  |     ^^^
  |

illegal-floating-point-literal-pattern

此 lint 检测模式中使用的浮点数字面量。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x = 42.0;

match x {
    5.0 => {},
    _ => {},
}
#}

这将产生:

warning: floating-point literals cannot be used in patterns
 --> src/main.rs:4:9
  |
4 |         5.0 => {},
  |         ^^^
  |
  = note: #[warn(illegal_floating_point_literal_pattern)] 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 #41620 <https://github.com/rust-lang/rust/issues/41620>

improper-ctypes

此 lint 检测到外部模块中, libc 类型的正确使用。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
extern "C" {
    static STATIC: String;
}
#}

这将产生:

warning: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
 --> src/main.rs:2:20
  |
2 |     static STATIC: String;
  |                    ^^^^^^
  |

late-bound-lifetime-arguments

???

此 lint 使用后绑定生命周期参数,检测路径片段中的泛型生存周期参数。一些触发此 lint 的示例代码:

struct S;

impl S {
    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
}

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

这将产生:

warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
 --> src/main.rs:8:14
  |
4 |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
  |             -- the late bound lifetime parameter is introduced here
...
8 |     S.late::<'static>(&0, &0);
  |              ^^^^^^^
  |
  = note: #[warn(late_bound_lifetime_arguments)] 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 #42868 <https://github.com/rust-lang/rust/issues/42868>

non-camel-case-types

此 lint 检测没有驼峰形式名称的类型,变体,trait 和类型参数。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
struct s;
#}

这将产生:

warning: type `s` should have a camel case name such as `S`
 --> src/main.rs:1:1
  |
1 | struct s;
  | ^^^^^^^^^
  |

non-shorthand-field-patterns

此 lint 检测在一个模式中,使用Struct { x: x }能代替Struct { x }。一些触发此 lint 的示例代码:

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
  --> src/main.rs:14:17
   |
14 |         Point { x: x, y: y } => (),
   |                 --^^
   |                 |
   |                 help: remove this
   |

warning: the `y:` in this pattern is redundant
  --> src/main.rs:14:23
   |
14 |         Point { x: x, y: y } => (),
   |                       --^^
   |                       |
   |                       help: remove this

non-snake-case

此 lint 检测没有蛇形式名称的变量,方法,函数,生命周期参数和模块。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let X = 5;
#}

这将产生:

warning: variable `X` should have a snake case name such as `x`
 --> src/main.rs:2:9
  |
2 |     let X = 5;
  |         ^
  |

non-upper-case-globals

此 lint 检测不大写的静态常量。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
static x: i32 = 5;
#}

这将产生:

warning: static variable `x` should have an upper case name such as `X`
 --> src/main.rs:1:1
  |
1 | static x: i32 = 5;
  | ^^^^^^^^^^^^^^^^^^
  |

no-mangle-generic-items

此 lint 检测泛型项必须被修复(mangle)。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
#[no_mangle]
fn foo<T>(t: T) {

}
#}

这将产生:

warning: functions generic over types must be mangled
 --> src/main.rs:2:1
  |
1 |   #[no_mangle]
  |   ------------ help: remove this attribute
2 | / fn foo<T>(t: T) {
3 | |
4 | | }
  | |_^
  |

path-statements

此 lint 检测路径语句无效。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x = 42;

x;
#}

这将产生:

warning: path statement with no effect
 --> src/main.rs:3:5
  |
3 |     x;
  |     ^^
  |

patterns-in-fns-without-body

这个 lint 检测到以前的错误,就是没有身体的函数模式。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
trait Trait {
    fn foo(mut arg: u8);
}
#}

这将产生:

warning: patterns aren't allowed in methods without bodies
 --> src/main.rs:2:12
  |
2 |     fn foo(mut arg: u8);
  |            ^^^^^^^
  |
  = note: #[warn(patterns_in_fns_without_body)] 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 #35203 <https://github.com/rust-lang/rust/issues/35203>

要解决此问题,请删除该模式; 它可以在实现中使用,而无需在定义中使用mut。那是:


# #![allow(unused_variables)]
#fn main() {
trait Trait {
    fn foo(arg: u8);
}

impl Trait for i32 {
    fn foo(mut arg: u8) {

    }
}
#}

plugin-as-library

此 lint 检测,当编译器插件用作非插件包中的普通库。一些触发此 lint 的示例代码:

#![feature(plugin)]
#![plugin(macro_crate_test)]

extern crate macro_crate_test;

private-in-public

此 lint 检测未被旧实现捕获的公有接口中的私有项。一些触发此 lint 的示例代码:

pub trait Trait {
    type A;
}

pub struct S;

mod foo {
    struct Z;

    impl ::Trait for ::S {
        type A = Z;
    }
}
# fn main() {}

这将产生:

error[E0446]: private type `foo::Z` in public interface
  --> src/main.rs:11:9
   |
11 |         type A = Z;
   |         ^^^^^^^^^^^ can't leak private type

private-no-mangle-fns

此 lint 检测标记#[no_mangle]的函数,这也是私有的。鉴于私有函数不公开,并且#[no_mangle]控制公有符号,这种组合是错误的。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
#[no_mangle]
fn foo() {}
#}

这将产生:

warning: function is marked #[no_mangle], but not exported
 --> src/main.rs:2:1
  |
2 | fn foo() {}
  | -^^^^^^^^^^
  | |
  | help: try making it public: `pub`
  |

要解决此问题,请将其公有或删除#[no_mangle]

private-no-mangle-statics

此 lint 检测到标记#[no_mangle]的任何静态是私有的。鉴于私有静态不公开,并且#[no_mangle]控制公共符号,这种组合是错误的。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
#[no_mangle]
static X: i32 = 4;
#}

这将产生:

warning: static is marked #[no_mangle], but not exported
 --> src/main.rs:2:1
  |
2 | static X: i32 = 4;
  | -^^^^^^^^^^^^^^^^^
  | |
  | help: try making it public: `pub`
  |

要解决此问题,请将其公开或删除#[no_mangle]

renamed-and-removed-lints

此 lint 检测已重命名或删除的 lint。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#![deny(raw_pointer_derive)]
#fn main() {
#}

这将产生:

warning: lint raw_pointer_derive has been removed: using derive with raw pointers is ok
 --> src/main.rs:1:9
  |
1 | #![deny(raw_pointer_derive)]
  |         ^^^^^^^^^^^^^^^^^^
  |

要解决此问题,请删除 lint 或使用新名称。

safe-packed-borrows

此 lint 检测借用除 1 之外的压缩对齐结构内部的字段。触发此 lint 的一些示例代码:

#[repr(packed)]
pub struct Unaligned<T>(pub T);

pub struct Foo {
    start: u8,
    data: Unaligned<u32>,
}

fn main() {
    let x = Foo { start: 0, data: Unaligned(1) };
    let y = &x.data.0;
}

这将产生:

warning: borrow of packed field requires unsafe function or block (error E0133)
  --> src/main.rs:11:13
   |
11 |     let y = &x.data.0;
   |             ^^^^^^^^^
   |
   = note: #[warn(safe_packed_borrows)] 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 #46043 <https://github.com/rust-lang/rust/issues/46043>

stable-features

此 lint 检测#[feature]的属性变得稳定了。一些触发此 lint 的示例代码:这将产生:


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

要修复,只需删除

warning: this feature has been stable since 1.0.0. Attribute no longer needed
 --> src/main.rs:1:12
  |
1 | #![feature(test_accepted_feature)]
  |            ^^^^^^^^^^^^^^^^^^^^^
  |

属性,因为它不再需要。#![feature]类型的别名边界

type-alias-bounds

这 lint 检测类型别名的边界。目前未被执行。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
type SendVec<T: Send> = Vec<T>;
#}

这将产生:

warning: type alias is never used: `SendVec`
 --> src/main.rs:1:1
  |
1 | type SendVec<T: Send> = Vec<T>;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |

tyvar-behind-raw-pointer

此 lint 检测指向一个推断变量的原始指针。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let data = std::ptr::null();
let _ = &data as *const *const ();

if data.is_null() {}
#}

这将产生:

warning: type annotations needed
 --> src/main.rs:4:13
  |
4 |     if data.is_null() {}
  |             ^^^^^^^
  |
  = note: #[warn(tyvar_behind_raw_pointer)] on by default
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
  = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>

unconditional-recursion

此 lint 检测在不调用自身的情况下,无法返回的函数。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
fn foo() {
    foo();
}
#}

这将产生:

warning: function cannot return without recursing
 --> src/main.rs:1:1
  |
1 | fn foo() {
  | ^^^^^^^^ cannot return without recursing
2 |     foo();
  |     ----- recursive call site
  |

unions-with-drop-fields

此 lint 检测联合的使用,其包含可能是重要丢弃代码的字段。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#![feature(untagged_unions)]

#fn main() {
union U {
    s: String,
}
#}

这将产生:

warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
 --> src/main.rs:4:5
  |
4 |     s: String,
  |     ^^^^^^^^^
  |

unknown-lints

此 lint 检测无法识别的 lint 属性。一些触发此 lint 的示例代码:

#[allow(not_a_real_lint)]

这将产生:

warning: unknown lint: `not_a_real_lint`
 --> src/main.rs:1:10
  |
1 | #![allow(not_a_real_lint)]
  |          ^^^^^^^^^^^^^^^
  |

unreachable-code

此 lint 检测无法访问的代码路径。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
panic!("we never go past here!");

let x = 5;
#}

这将产生:

warning: unreachable statement
 --> src/main.rs:4:5
  |
4 |     let x = 5;
  |     ^^^^^^^^^^
  |

unreachable-patterns

此 lint 检测到无法访问的模式。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x = 5;
match x {
    y => (),
    5 => (),
}
#}

这将产生:

warning: unreachable pattern
 --> src/main.rs:5:5
  |
5 |     5 => (),
  |     ^
  |

y模式永远匹配,所以五个是不可能达到的。记住,匹配武器按顺序匹配,你可能想把它5上面的案例y案件。

unstable-name-collision

此 lint 检测到您使用了标准库计划在将来添加的名称,这意味着将来如果没有其他类型注释,您的代码可能无法编译。请重命名,或立即添加这些注释。

unused-allocation

此 lint 检测可以消除的不必要的内存分配。

unused-assignments

此 lint 检测永远不会读取的内存分配。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let mut x = 5;
x = 6;
#}

这将产生:

warning: value assigned to `x` is never read
 --> src/main.rs:4:5
  |
4 |     x = 6;
  |     ^
  |

unused-attributes

此 lint 检测编译器未使用的属性。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#![feature(custom_attribute)]

#![mutable_doc]
#fn main() {
#}

这将产生:

warning: unused attribute
 --> src/main.rs:4:1
  |
4 | #![mutable_doc]
  | ^^^^^^^^^^^^^^^
  |

unused-comparisons

此 lint 检测到所涉及的类型限制使得 比较操作 变得无用。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
fn foo(x: u8) {
    x >= 0;
}
#}

这将产生:

warning: comparison is useless due to type limits
 --> src/main.rs:6:5
  |
6 |     x >= 0;
  |     ^^^^^^
  |

unused-doc-comment

此 lint 检测 rustdoc 未使用的 doc 注释。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
/// docs for x
let x = 12;
#}

这将产生:

warning: doc comment not used by rustdoc
 --> src/main.rs:2:5
  |
2 |     /// docs for x
  |     ^^^^^^^^^^^^^^
  |

unused-features

此 lint 检测在 crate-level 的#[feature]指令 中,找到的未使用或未知功能。要解决此问题,只需删除功能标志即可。

unused-imports

此 lint 检测从未使用过的导入。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
use std::collections::HashMap;
#}

这将产生:

warning: unused import: `std::collections::HashMap`
 --> src/main.rs:1:5
  |
1 | use std::collections::HashMap;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
  |

unused-macros

此 lint 检测未使用的宏。一些触发此 lint 的示例代码:

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

fn main() {
}

这将产生:

warning: unused macro definition
 --> src/main.rs:1:1
  |
1 | / macro_rules! unused {
2 | |     () => {};
3 | | }
  | |_^
  |

unused-must-use

此 lint 检测标记为#[must_use]的类型的未使用结果。一些触发此 lint 的示例代码:

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

fn main() {
    returns_result();
}

这将产生:

warning: unused `std::result::Result` that must be used
 --> src/main.rs:6:5
  |
6 |     returns_result();
  |     ^^^^^^^^^^^^^^^^^
  |

unused-mut

此 lint 检测不需要可变的 mut 变量。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let mut x = 5;
#}

这将产生:

warning: variable does not need to be mutable
 --> src/main.rs:2:9
  |
2 |     let mut x = 5;
  |         ----^
  |         |
  |         help: remove this `mut`
  |

unused-parens

这个棉绒检测到ifmatchwhilereturn括号;他们不需要他们。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
if(true) {}
#}

这将产生:

warning: unnecessary parentheses around `if` condition
 --> src/main.rs:2:7
  |
2 |     if(true) {}
  |       ^^^^^^ help: remove these parentheses
  |

unused-unsafe

这个 lint 检测到不必要的使用unsafe块。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
unsafe {}
#}

这将产生:

warning: unnecessary `unsafe` block
 --> src/main.rs:2:5
  |
2 |     unsafe {}
  |     ^^^^^^ unnecessary `unsafe` block
  |

unused-variables

此 lint 检测未以任何方式使用的变量。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x = 5;
#}

这将产生:

warning: unused variable: `x`
 --> src/main.rs:2:9
  |
2 |     let x = 5;
  |         ^ help: consider using `_x` instead
  |

warnings

这种 lint 有点特别;通过更改其级别,您可以更改每个其他警告,这些警告会对您想要的任何值产生警告:


# #![allow(unused_variables)]
#![deny(warnings)]
#fn main() {
#}

因此,您不会直接在代码中触发此 lint。

while-true

这个 lint 检测到while true { }。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
while true {

}
#}

这将产生:

warning: denote infinite loops with `loop { ... }`
 --> src/main.rs:2:5
  |
2 |     while true {
  |     ^^^^^^^^^^ help: use `loop`
  |

默认拒绝的 lints

默认情况下,这些 lint 都设置为’deny’级别。

exceeding-bitshifts

此 lint 检测到移位超出了类型的位数。一些触发此 lint 的示例代码:

1_i32 << 32;

这将产生:

error: bitshift exceeds the type's number of bits
 --> src/main.rs:2:5
  |
2 |     1_i32 << 32;
  |     ^^^^^^^^^^^
  |

invalid-type-param-default

此 lint 检测在无效位置中,允许的类型参数默认值错误。一些触发此 lint 的示例代码:

fn foo<T=i32>(t: T) {}

这将产生:

error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
 --> src/main.rs:4:8
  |
4 | fn foo<T=i32>(t: T) {}
  |        ^
  |
  = note: #[deny(invalid_type_param_default)] 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 #36887 <https://github.com/rust-lang/rust/issues/36887>

legacy-constructor-visibility

RFC 1506修改了一些可见性规则,并改变了 struct 构造函数的可见性。一些触发此 lint 的示例代码:

mod m {
    pub struct S(u8);

    fn f() {
        // this is trying to use S from the 'use' line, but because the `u8` is
        // not pub, it is private
        ::S;
    }
}

use m::S;

这将产生:

error: private struct constructors are not usable through re-exports in outer modules
 --> src/main.rs:5:9
  |
5 |         ::S;
  |         ^^^
  |
  = note: #[deny(legacy_constructor_visibility)] 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 #39207 <https://github.com/rust-lang/rust/issues/39207>

legacy-directory-ownership

发出 legacy_directory_ownership 时发出

  • 有一个带有#[path]属性的非内联模块(例如#[path = "foo.rs"]mod bar;),
  • 模块的文件(上例中的“foo.rs”)是未命名为“mod.rs”,并且
  • 模块的文件包含一个#[path]属性的非内联模块。

可以通过将父模块重命名为“mod.rs”,并将其移动到其自己的目录(如果合适的话)来修复警告。

missing-fragment-specifier

当一个未使用的macro_rules!宏定义模式出现时,会发出 missing_fragment_specifier 警告,因其有一个元变量(例如$e)后面没有片段说明符(例如:expr)。

通过删除未使用的macro_rules!宏定义模式,可以始终修复此警告。

mutable-transmutes

这种 lint 抓取&T&mut T的转化,因为它是未定义的行为。一些触发此 lint 的示例代码:

unsafe {
    let y = std::mem::transmute::<&i32, &mut i32>(&5);
}

这将产生:

error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
 --> src/main.rs:3:17
  |
3 |         let y = std::mem::transmute::<&i32, &mut i32>(&5);
  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |

no-mangle-const-items

这个 lint 检测到任何带#[no_mangle]属性的const项。常量确实没有导出符号,因此,这可能意味着您打算使用static不是const。一些触发此 lint 的示例代码:

#[no_mangle]
const FOO: i32 = 5;

这将产生:

error: const items should never be #[no_mangle]
 --> src/main.rs:3:1
  |
3 | const FOO: i32 = 5;
  | -----^^^^^^^^^^^^^^
  | |
  | help: try a static value: `pub static`
  |

overflowing-literals

此 lint 检测其类型的字面值超出范围。一些触发此 lint 的示例代码:


# #![allow(unused_variables)]
#fn main() {
let x: u8 = 1000;
#}

这将产生:

error: literal out of range for u8
 --> src/main.rs:2:17
  |
2 |     let x: u8 = 1000;
  |                 ^^^^
  |

parenthesized-params-in-types-and-modules

此 lint 检测到不正确的括号。一些触发此 lint 的示例代码:

let x = 5 as usize();

这将产生:

error: parenthesized parameters may only be used with a trait
 --> src/main.rs:2:21
  |
2 |   let x = 5 as usize();
  |                     ^^
  |
  = note: #[deny(parenthesized_params_in_types_and_modules)] 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 #42238 <https://github.com/rust-lang/rust/issues/42238>

要修复它,请删除多个()

pub-use-of-private-extern-crate

此 lint 检测重新导出一个私有extern crate的特定情况;

safe-extern-statics

在旧版本的 Rust 中,允许extern static以安全代码访问,会存在安全问题。这个 lint 现在抓住并否认这种代码。

unknown-crate-types

此 lint 检测到在一个#[crate_type]指示中,发现一个未知箱类型。一些触发此 lint 的示例代码:

#![crate_type="lol"]

这将产生:

error: invalid `crate_type` value
 --> src/lib.rs:1:1
  |
1 | #![crate_type="lol"]
  | ^^^^^^^^^^^^^^^^^^^^
  |

incoherent-fundamental-impls

此 lint 检测到错误允许的潜在冲突的 impl。一些触发此 lint 的示例代码:

pub trait Trait1<X> {
    type Output;
}

pub trait Trait2<X> {}

pub struct A;

impl<X, T> Trait1<X> for T where T: Trait2<X> {
    type Output = ();
}

impl<X> Trait1<Box<X>> for A {
    type Output = i32;
}

这将产生:

error: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
  --> src/main.rs:13:1
   |
9  | impl<X, T> Trait1<X> for T where T: Trait2<X> {
   | --------------------------------------------- first implementation here
...
13 | impl<X> Trait1<Box<X>> for A {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
   |
   = note: #[deny(incoherent_fundamental_impls)] 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 #46205 <https://github.com/rust-lang/rust/issues/46205>
   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`

代码生成选项

所有这些选项都通过-C标志,传递给rustc,缩写“C = codegen”。通过运行rustc -C help,给出该版本的详细帮助列表。

ar

此选项已弃用,不起任何作用。

linker

此标志允许您控制,rustc调用哪个链接器来链接代码。

link-arg=val

此标志允许您向调用的链接器,附加一个额外参数。

重要“温馨提示”;您可以多次传递此标志,以添加多个参数。

link-args

此标志允许您向调用的链接器,附加多个额外参数。选项应以空格分隔。

linker-flavor

此标志允许您通过rustc控制链接器设置。如果提供的一个链接器与-C linker标志(上面描述的),然后根据提供的值推断链接器风格。如果没有提供链接器,则链接器风格可用来确定哪个链接器。每个rustc生成目标默认为某种链接器风格。

link-dead-code

通常,链接器会删除死代码。此标志禁用此行为。

一个例子是,当试图构造代码覆盖率的衡量时,这个标志可能有用的。

lto

此标志指示 LLVM 使用链接时间优化

它需要thinfat两个值中的一个,,’thin’的 LTO是 LLVM 的新功能,“fat”指 LTO 的经典版本。

target-cpu

这指示rustc为特定的处理器,生成专用代码。

你可以rustc --print target-cpus,查看在此处传递的有效选项。此外,native可以传递,本主机的处理器。

target-feature

单个目标将也支持不同的功能;此标志允许您控制启用或禁用功能。

要查看有效选项和使用示例,请运行rustc --print target-features.

passes

此标志可用于向编译器,添加额外的 LLVM 传递参数(passes)。

该列表必须用空格分隔。

llvm-args

此标志可用于将参数列表,直接传递给 LLVM。

该列表必须用空格分隔。

save-temps

rustc将在编译期间生成临时文件;通常在完成工作后将其删除。此选项将使它们保留而不是删除。

rpath

此选项允许您设置rpath的值。

overflow-checks

此标志允许您控制整数溢出的行为。此标志可以传递许多选项:

  • 打开溢出检查:yyes,或on.
  • 关闭溢出检查:nnooff.

no-prepopulate-passes

传递参数管理器预先填充了传递列表;此标志会确保列表为空。

no-vectorize-loops

默认情况下,rustc将尝试向量化循环。 此标志将关闭该行为。

no-vectorize-slp

默认情况下,rustc将尝试使用superword-level 并发. 此标志将关闭该行为。

soft-float

此选项让rustc使用“软浮动”生成代码。默认情况下,许多硬件支持浮点数指令,因此生成的代码将利用这一点。“软浮动”在软件中模拟浮点数指令。

prefer-dynamic

默认情况下,rustc倾向于静态链接依赖项。此选项将使其改用动态链接。

no-integrated-as

LLVM 附带一个内部汇编程序;此选项将允许您使用外部汇编程序。

no-redzone

此标志允许您禁用红色地带。 此标志可以传递许多选项:

  • 启用:yyeson.
  • 禁用:nnooff.

relocation-model

此选项允许您选择要使用的重新定位模型。

要查找此标志的有效选项,请运行rustc --print relocation-models.

code-model=val

此选项允许您选择要使用的代码模型。

要查找此标志的有效选项,请运行rustc --print code-models.

metadata

此选项允许您控制用于符号管理的元数据。

extra-filename

此选项允许您在每个输出文件名中,放置额外的数据。

codegen-units

此标志允许您控制在执行代码生成时,使用的线程数。

增加并行性可能会加快编译时间,但也可能产生较慢的运行代码。

remark

此标志允许您为这些优化过程打印备注。

传递参数列表应以空格分隔。

all:每个传递参数都要备注。

no-stack-check

此选项已弃用,不起任何作用。

debuginfo

此标志允许您控制调试信息:

  • 0:完全没有调试信息
  • 1:仅表格行
  • 2:完整的调试信息

opt-level

此标志允许您控制优化级别。

  • 0:无优化,也打开cfg(debug_assertions).
  • 1:基本优化
  • 2:一些优化
  • 3:所有优化
  • s:优化二进制大小
  • z:优化二进制大小,但也关闭向量化循环。

debug-assertions

这个标志让你,控制cfg(debug_assertions)打开或关闭。

inline-threshold

此选项允许您设置内联一个函数的阈值。

默认值为 225。

panic

此选项允许您控制代码恐慌时,发生的情况。

  • abort:紧急终止进程
  • unwind:恐慌时打开堆栈

incremental

此标志允许您启用强化编译。

生成目标

rustc默认情况下是跨平台编译器。这意味着,您可以用编译器来构建任何体系结构。目标列表是您可以构建的可能架构。

要查看可以设置的,生成目标的所有选项,请参阅这里的文档。

要编译到特定目标,请使用--target标志:

$ rustc src/main.rs --target=wasm32-unknown-unknown

内置目标

rustc能够自动编译到多个目标,我们称之为“内置”目标,它们通常对应团队直接支持的目标。

要查看内置目标列表,您可以运行rustc --print target-list,或者看看API 文档。每个模块为特定目标,都定义了一个构建器。

自定义目标

如果您想为尚未支持的目标构建rustc,您可以使用“自定义目标规范”来定义目标。这些目标规范文件是 JSON。要查看主机目标的 JSON,您可以运行:

$ rustc +nightly -Z unstable-options --print target-spec-json

要查看其他目标,请添加--target标志:

$ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json

要使用自定义目标,请参阅xargo

Linker-plugin-LTO

-C linker-plugin-lto标志 允许将 LTO 优化推迟到实际链接步骤,如果链接的所有目标文件都是由基于 LLVM 的工具链创建的,则相应地允许跨编程语言,执行过程优化。这里的主要示例是将 Rust 代码与 Clang 编译的 C/C++代码链接在一起。

用法

有两种主要情况,可以使用基于 LTO 的链接器插件:

  • 编译一个 Ruststaticlib,用作一个 C ABI 依赖项
  • 编译一个 Rust 二进制文件,这里是rustc调用链接器

在这两种情况下,Rust 代码都必须使用-C linker-plugin-lto和 C/C++代码要用-flto-flto=thin,以便将目标文件作为 LLVM bitcode 发出。

Ruststaticlib作为 C/C++程序中的依赖

在这种情况下,Rust 编译器只需要确保staticlib的对象文件格式正确。对于链接,必须使用具有 LLVM 的链接器插件(例如 LLD)。

直接用rustc

# 编译 the Rust staticlib
rustc --crate-type=staticlib -Clinker-plugin-lto -Copt-level=2 ./lib.rs
# `-flto=thin`编译 C 代码
clang -c -O2 -flto=thin -o main.o ./main.c
# 链接 一切,确保 我们使用适当的链接器
clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o

运用cargo

# 编译 the Rust staticlib
RUSTFLAGS="-Clinker-plugin-lto" cargo build --release
# `-flto=thin`编译 C 代码
clang -c -O2 -flto=thin -o main.o ./main.c
# 链接 一切,确保 我们使用适当的链接器
clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o

C/C++代码作为 Rust 中的依赖项

在这种情况下,链接器将被rustc调用。我们必须再次确保使用适当的链接器。

直接用rustc

# 编译 C code with `-flto`
clang ./clib.c -flto=thin -c -o ./clib.o -O2
# 拿C 代码,创建一个静态库
ar crus ./libxyz.a ./clib.o

# 附加参数,调用 `rustc`
rustc -Clinker-plugin-lto -L. -Copt-level=2 -Clinker=clang -Clink-arg=-fuse-ld=lld ./main.rs

直接用cargo

# 编译 C code with `-flto`
clang ./clib.c -flto=thin -c -o ./clib.o -O2
# 拿C 代码,创建一个静态库
ar crus ./libxyz.a ./clib.o

# 通过 RUSTFLAGS,设链接的参数
RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release

rustc明确指定要使用的链接器插件

如果想要使用 LLD 以外的链接器,则必须明确指定 LLVM 链接器插件。否则链接器无法读取目标文件。插件的路径作为参数传递给-Clinker-plugin-lto选项:

rustc -Clinker-plugin-lto="/path/to/LLVMgold.so" -L. -Copt-level=2 ./main.rs

工具链兼容性

为了使这种 LTO 工作,LLVM 链接器插件必须能够处理由rustcclang两者生成的 LLVM bitcode。

使用一个rustcclang可以获得最佳效果,它们基于完全相同的 LLVM 版本。可以使用rustc -vV,查看给定rustc版本的 LLVM。请注意,此处给出的版本号只是一个近似值,因为 Rust 有时会使用不稳定的 LLVM 修订版。但是,近似值通常是可靠的。

下表,显示了工具链版本的已知良好组合。

Clang 7 Clang 8
Rust 1.34
Rust 1.35 ✓(?)

请注意,此功能的兼容性策略将来可能会更改。

帮助rustc

很乐意有你帮助我们改善rustc!为此,我们写了本升级版,关于它的内部,如何工作,以及如何与rustc搭配工作。要了解更多信息,您需要检查一下。

如果你想帮助这个书,你可以在src/doc/rustc找到它。