预导入包

use-declarations.md
commit: 0ce54e64e3c98d99862485c57087d0ab36f40ef0
本章译文最后维护日期:2021-1-24

预导入包是一组名称的集合,它会自动把这些名称导入到 crate 中的每个模块的作用域中。

预导入包中的那些名称不是当前模块本身的一部分,它们在名称解析期间被隐式导入。例如,即使像 Box 这样在每个模块的作用域中到处使用的名称,你也不能通过 self::Box 来引用它,因为它不是当前模块的成员。

有几个不同的预导入包:

标准库预导入包

标准库预导入包包含了 std::prelude::v1模块中的名称。如果使用no_std属性,那么它将使用core::prelude::v1模块中的名称。

外部预导入包

在根模块中使用 extern crate 导入的外部crate 或直接给编译器提供的的外部crate(也就是在 rustc命令下使用 --extern命令行参数选项)会被添加到外部预导入包中。如果使用 extern crate orig_name as new_name 这类别名导入,则符号 new_name 将被添加到此预导入包。

core crate 总是会被添加到外部预导入包中。只要 no_std属性没有在 crate根模块中指定,那么std crate 就会被添加进来

版本差异:在 2015 版中,在外部预导入包中的 crate 不能通过 use声明来直接引用,因此通常标准做法是用 extern crate 将那它们纳入到当前作用域。

从 2018 版开始, use声明可以直接引用外部预导入包里的 crate,所以再在代码里使用 extern crate 就会被认为是不规范的。

注意: 随 rustc 一起引入的 crate,如 alloctest,在使用 Cargo 时不会自动被包含在 --extern 命令行参数选项中。即使在 2018 版中,也必须通过外部crate(extern crate)声明来把它们引入到当前作用域内。

#![allow(unused)]
fn main() {
extern crate alloc;
use alloc::rc::Rc;
}

Cargo却会将 proc_macro 带入到编译类型为 proc-macro 的 crate 的外部预导入包中

no_std属性

默认情况下,标准库自动包含在 crate根模块中。在 std crate 被添加到根模块中的同时,还会隐式生效一个 macro_use属性,它将所有从 std 中导出的宏放入到macro_use预导入包中。默认情况下,corestd 都被添加到外部预导入包中。标准库预导入包包含了 std::prelude::v1模块中的所有内容。

*no_std属性*可以应用在 crate 级别上,用来防止 std crate 被自动添加到相关作用域内。此属性作了如下三件事:

注意:当 crate 的目标平台不支持标准库或者故意不使用标准库的功能时,使用核心预导入包而不是标准预导入包是很有用的。此时没有导入的标准库的那些功能主要是动态内存分配(例如:Box和' Vec)和文件,以及网络功能(例如:std::fsstd::io)。

警告:使用 no_std 并不会阻止标准库被链接进来。使用 extern crate std;std crate 导入仍然有效,相关的依赖项也可以被正常链接进来。

语言预导入包

语言预导入包包括语言内置的类型名称和属性名称。语言预导入包总是在当前作用域内有效的。它包括以下内容:

macro_use预导入包

macro_use预导入包包含了外部crate 中的宏,这些宏是通过在当前文档源码内部的 extern crate 声明语句上应用 macro_use属性来导入此声明中的 crate 内部的宏。

工具类预导入包

工具类预导入包包含了在类型命名空间中声明的外部工具的工具名称。请参阅工具类属性一节,以了解更多细节。

no_implicit_prelude属性

*no_implicit_prelude属性*可以应用在 crate级别或模块上,用以指示它不应该自动将标准库预导入包外部预导入包工具类预导入包引入到当前模块或其任何子模块的作用域中。

此属性不影响语言预导入包

版本差异: 在 2015版中,no_implicit_prelude属性不会影响macro_use预导入包,从标准库导出的所有宏仍然包含在 macro_use预导入包中。从 2018版开始,它也会禁止 macro_use预导入包生效。