预定义
预定义 是一组自动引入到一个 crate 中每个模块作用域的名称。
这些预定义名称不是模块本身的一部分: 它们在 命名解析 期间隐式查询。例如,即使像 Box 这样的内容在每个模块中都处于作用域中,但你无法将其称为 self::Box ,因为它不是当前模块的成员。
有几个不同的预定义:
标准库预定义
每个 crate 都有一个标准库预定义,其中包括来自单个标准库模块的名称。所使用的模块取决于 crate 的版本,以及是否应用了 no_std属性 :
| 版本 | 未应用no_std | 应用no_std |
|---|---|---|
| 2015 | std::prelude::rust_2015 | core::prelude::rust_2015 |
| 2018 | std::prelude::rust_2018 | core::prelude::rust_2018 |
| 2021 | std::prelude::rust_2021 | core::prelude::rust_2021 |
注意:
std::prelude::rust_2015和std::prelude::rust_2018的内容与std::prelude::v1相同。
core::prelude::rust_2015和core::prelude::rust_2018的内容与core::prelude::v1相同。
外部预定义
在根模块中使用 extern crate 导入的外部 crate 或提供给编译器的 crate (例如使用 rustc 的 --extern 标志) 将被添加到 外部定义 中。如果使用别名导入,例如 extern crate orig_name as new_name ,则符号 new_name 将添加到预定义中。
core crate 始终会被添加到外部预定义中。只要在 crate 根中未指定 [no_std属性] , std crate 也会被添加到预定义中。
版本差异: 在 2015 版中,外部预定义中的 crate 不能通过 use 声明 引用,因此通常的做法是使用
extern crate声明将它们引入作用域。从 2018 年版开始, use 声明 可以引用外部预定义中的 crate ,因此使用
extern crate被认为不符合惯例。
注意: 随
rustc一起提供的其他 crate ,例如alloc和test,在使用 Cargo 时不会自动包含在--extern标志中。它们必须通过extern crate声明引入作用域,即使在 2018 版中也是如此。#![allow(unused)] fn main() { extern crate alloc; use alloc::rc::Rc; }对于 proc-macro crate , Cargo 会将
proc_macro自动添加到外部预定义中。
no_std 属性
默认情况下,标准库会自动包含在 crate 的根模块中。std crate 与一个隐式的 macro_use 属性 一同添加到根模块,将 std 导出的所有宏都添加到 macro_use 预定义模块 中。同时,core 和 std 也会添加到 extern 预定义 中。
可以在 crate 级别应用 no_std 属性 来阻止自动将 std crate 添加到作用域中。会做三件事情:
- 防止
std添加到 extern 预定义 中。 - 影响用于构建 标准库预定义 的模块 (如上所述) 。
- 将
corecrate 注入到 crate 根模块中,而不是std,并将所有从core导出的宏添加到macro_use预定义模块 中。
注意: 当 crate 目标平台不支持标准库或有意不使用标准库的功能时,使用核心预定义而不是标准库预定义很有用。 这些功能主要包括动态内存分配 (例如
Box和Vec) 以及文件和网络功能 (例如std::fs和std::io) 。
警告: 使用 no_std 不会防止标准库被链接。在 crate 中放置 extern crate std; 是有效的,依赖项依然可以链接它。
语言预定义
语言预定义包括内置于语言中的类型和属性名称。语言预定义始终在作用域内。包括以下内容:
- 类型命名空间
- 布尔类型 —
bool - 文本类型 —
char和str - 整数类型 —
i8、i16、i32、i64、i128、u8、u16、u32、u64、u128 - 与机器相关的整数类型 —
usize和isize - 浮点数类型 —
f32和f64
- 布尔类型 —
- 宏命名空间
macro_use 预定义
macro_use 预定义包括来自外部 crate 的宏,这些宏是通过 [macro_use] 属性定义的。
工具预定义
工具预定义包括外部工具的工具名称,位于 类型命名空间 中。有关详细信息,请参见 工具属性 部分。
no_implicit_prelude 属性
no_implicit_prelude attribute 可以应用于 crate 级别或模块上,表示它不应自动为该模块或其任何子级引入 标准库预定义、 extern 预定义 或 工具预定义 。
该属性不影响 语言预定义 。
版本差异:在 2015 版中,
no_implicit_prelude属性不影响macro_use预定义 ,并且标准库导出的所有宏仍包含在macro_use预定义中。从 2018 版开始,将移除macro_use预定义。