包和源文件
Syntax
Crate →
InnerAttribute*
Item*
Note
虽然 Rust 与任何其他语言一样,可以通过解释器和编译器来实现,但现有的唯一实现是编译器,并且该语言一直是为编译而设计的。因此,本节假定使用编译器。
Rust 的语义遵循编译时和运行时之间的阶段区分。1 具有静态解释的语义规则支配编译的成功或失败,而具有动态解释的语义规则支配程序在运行时的行为。
编译模型以称为 crate 的工件为中心。每个编译处理一个源形式的 crate,如果成功,则产生一个二进制形式的 crate:可执行文件或某种库。2
crate 是编译和链接的单元,也是版本控制、分发和运行时加载的单元。crate 包含嵌套模块作用域的_树_。此树的顶层是一个模块,它是匿名的(从模块内的路径角度来看),crate 内的任何项都有一个规范的模块路径,表示其在 crate 模块树中的位置。
Rust 编译器始终以单个源文件作为输入调用,并始终产生单个输出 crate。该源文件的处理可能导致其他源文件作为模块加载。源文件的扩展名为 .rs。
Rust 源文件描述一个模块,该模块的名称和位置 — 在当前 crate 的模块树中 — 是从源文件外部定义的:要么通过引用源文件中的显式 Module 项,要么通过 crate 本身的名称。
每个源文件都是一个模块,但不是每个模块都需要自己的源文件:模块定义可以嵌套在一个文件中。
每个源文件包含零个或多个 Item 定义的序列,并且可以选择以应用于包含模块的任意数量的属性开头,其中大部分会影响编译器的行为。
匿名 crate 模块可以有应用于整个 crate 的额外属性。
Note
文件的内容前面可以有 shebang。
#![allow(unused)]
fn main() {
// Specify the crate name.
#![crate_name = "projx"]
// Specify the type of output artifact.
#![crate_type = "lib"]
// Turn on a warning.
// This can be done in any module, not just the anonymous crate module.
#![warn(non_camel_case_types)]
}
Main 函数
包含 main 函数的 crate 可以编译为可执行文件。
如果存在 main 函数,它必须不带参数,不能声明任何 trait 或生命周期约束,不能有任何 where 子句,并且其返回类型必须实现 Termination trait。
fn main() {}
fn main() -> ! {
std::process::exit(0);
}
fn main() -> impl std::process::Termination {
std::process::ExitCode::SUCCESS
}
main 函数可以是导入的,例如来自外部 crate 或当前 crate。
#![allow(unused)]
fn main() {
mod foo {
pub fn bar() {
println!("Hello, world!");
}
}
use foo::bar as main;
}
Note
标准库中具有
Termination实现的类型包括:
()!InfallibleExitCodeResult<T, E> where T: Termination, E: Debug
未捕获的外部展开
当“外部“展开(例如,从 C++ 代码抛出的异常,或使用不同 panic 处理器的 Rust 代码中的 panic!)传播到 main 函数之外时,进程将被安全终止。这可能以中止的形式发生,在这种情况下,不保证执行任何 Drop 调用,并且错误输出可能不如运行时被“本机“ Rust panic 终止时那么信息丰富。
有关更多信息,请参阅 panic 文档。
no_main 属性
no_main 属性 可以应用于 crate 级别,以禁用为可执行二进制文件发出 main 符号。当链接的其他对象定义了 main 时,这很有用。
crate_name 属性
crate_name 属性 可以应用于 crate 级别,以使用 MetaNameValueStr 语法指定 crate 的名称。
#![allow(unused)]
#![crate_name = "mycrate"]
fn main() {
}
crate 名称不能为空,并且只能包含 Unicode 字母数字或 _ (U+005F) 字符。