箱和源文件

语法

:

   内部属性*

   项目*

注意:尽管 Rust 和任何其他语言一样,可以通过解释器和编译器来实现,但目前唯一存在的实现是编译器,而且该语言的设计初衷就是为了编译。因此,本节假设使用编译器。

Rust 的语义遵循编译时和运行时之间的阶段区分1 具有静态解释的语义规则控制编译的成功或失败,而具有动态解释的语义规则控制程序在运行时的行为。

编译模型的核心是称为的工件。每次编译都会处理源代码形式的单个箱,如果成功,则会生成二进制形式的单个箱:可执行文件或某种库。2

是编译、链接、版本控制、分发和运行时加载的单元。一个箱包含一个嵌套的 模块 作用域。这棵树的顶层是一个匿名模块(从模块内路径的角度来看),并且箱内的任何项目都有一个规范的 模块路径 来表示其在箱的模块树中的位置。

Rust 编译器始终以单个源文件作为输入被调用,并且始终生成单个输出箱。该源文件的处理可能会导致其他源文件作为模块被加载。源文件的扩展名为 .rs

Rust 源文件描述了一个模块,该模块的名称和位置(在当前箱的模块树中)是在源文件外部定义的:通过引用源文件中的显式 模块 项目,或者通过箱本身的名称来定义。每个源文件都是一个模块,但并非每个模块都需要自己的源文件:模块定义 可以嵌套在一个文件中。

每个源文件都包含零个或多个 项目 定义的序列,并且可以选择以任意数量的应用于包含模块的 属性 开头,其中大多数属性会影响编译器的行为。匿名箱模块可以具有应用于整个箱的其他属性。

注意:文件的内容前面可以有 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)]
}

前奏和 no_std

本节已移至前奏章节

主函数

包含 main 函数 的箱可以编译成可执行文件。如果存在 main 函数,则它必须不带任何参数,不得声明任何 特征或生命周期边界,不得有任何 where 子句,并且其返回类型必须实现 Termination 特征。

fn main() {}
fn main() -> ! {
    std::process::exit(0);
}
fn main() -> impl std::process::Termination {
    std::process::ExitCode::SUCCESS
}

main 函数可以是导入的,例如从外部箱或当前箱导入。

#![allow(unused)]
fn main() {
mod foo {
    pub fn bar() {
        println!("Hello, world!");
    }
}
use foo::bar as main;
}

注意:标准库中实现 Termination 的类型包括

no_main 属性

no_main 属性 可以应用于箱级别,以禁用为可执行二进制文件生成 main 符号。当链接到的其他某个对象定义了 main 时,这很有用。

crate_name 属性

crate_name 属性 可以应用于箱级别,以使用 MetaNameValueStr 语法指定箱的名称。

#![allow(unused)]
#![crate_name = "mycrate"]
fn main() {
}

箱名称不能为空,并且只能包含 Unicode 字母数字_ (U+005F) 字符。

1

这种区分在解释器中也存在。像语法分析、类型检查和 lint 这样的静态检查应该在程序执行之前进行,而不管程序何时执行。

2

箱有点类似于 ECMA-335 CLI 模型中的程序集、SML/NJ 编译管理器中的、Owens 和 Flatt 模块系统中的单元或 Mesa 中的配置