预导入
预导入是一组自动带入 crate 中每个模块作用域的名称集合。
这些预导入名称不是模块本身的一部分:它们在名称解析期间被隐式查询。例如,尽管像 Box 这样的名称在每个模块中都在作用域内,你不能将其引用为 self::Box,因为它不是当前模块的成员。
存在几种不同的预导入:
标准库预导入
每个 crate 都有一个标准库预导入,由来自单个标准库模块的名称组成。
所使用的模块取决于 crate 的版次以及 no_std 属性是否应用于 crate:
Note
std::prelude::rust_2015和std::prelude::rust_2018与std::prelude::v1具有相同的内容。
core::prelude::rust_2015和core::prelude::rust_2018与core::prelude::v1具有相同的内容。
Note
当
core::panic!或std::panic!之一由于标准库预导入被带入作用域,而用户编写的 glob 导入将另一个带入作用域时,rustc目前允许使用panic!,即使它是有歧义的。用户编写的 glob 导入优先以解决此歧义。详情请参见 names.resolution.expansion.imports.ambiguity.panic-hack。
外部 crate 预导入
在根模块中使用 extern crate 导入的或提供给编译器的(如使用 rustc 的 --extern 标志)外部 crate 被添加到外部 crate 预导入中。如果使用别名导入,例如 extern crate orig_name as new_name,则符号 new_name 被添加到预导入中。
core crate 始终被添加到外部 crate 预导入中。
只要在 crate 根中未指定 no_std 属性,std crate 就会被添加。
2018 Edition differences
在 2015 版次中,外部 crate 预导入中的 crate 不能通过 use 声明引用,因此通常的标准做法是包含
extern crate声明将其带入作用域。从 2018 版次开始,use 声明可以引用外部 crate 预导入中的 crate,因此使用
extern crate被认为是不惯用的。
Note
随
rustc一起分发的其他 crate,例如alloc和test,在使用 Cargo 时不会通过--extern标志自动包含。即使在 2018 版次中,也必须使用extern crate声明将其带入作用域。#![allow(unused)] fn main() { extern crate alloc; use alloc::rc::Rc; }对于仅 proc-macro crate,Cargo 确实会将
proc_macro引入外部 crate 预导入中。
no_std 属性
no_std 属性 导致 std crate 不被自动链接,并且标准库预导入改为使用 core 预导入。
Example
#![no_std]
Note
当 crate 面向不支持标准库的平台,或有目的地不使用标准库的功能时,使用
no_std是有用的。这些功能主要是动态内存分配(如Box和Vec)以及文件和网络功能(如std::fs和std::io)。
Warning
使用
no_std不会阻止标准库被链接。在 crate 或其依赖之一中写入extern crate std仍然是有效的;这将导致编译器将stdcrate 链接到程序中。
no_std 属性使用 MetaWord 语法。
no_std 属性只能应用于 crate 根。
no_std 属性可以在一个形式上使用任意次数。
Note
rustc会对第一次之后的使用发出 lint 警告。
no_std 属性将标准库预导入改为使用 core 预导入而非 std 预导入。
2018 Edition differences
在 2018 版次之前,
std默认被注入到 crate 根中。如果指定了no_std,则改为注入core。从 2018 版次开始,无论是否指定no_std,两者都不会被注入到 crate 根中。
语言预导入
语言预导入包括语言内置的类型和属性名称。语言预导入始终在作用域中。
它包括以下内容:
macro_use 预导入
macro_use 预导入包括通过对 extern crate 应用 macro_use 属性从外部 crate 导入的宏。
工具预导入
工具预导入包括类型命名空间中外部工具的工具名称。更多细节请参见工具属性部分。
no_implicit_prelude 属性
no_implicit_prelude 属性 用于阻止隐式预导入被带入作用域。
Example
#![allow(unused)] fn main() { // 该属性可以应用于 crate 根以影响所有模块。 #![no_implicit_prelude] // 或者可以应用于一个模块以仅影响该模块及其后代。 #[no_implicit_prelude] mod example { // ... } }
no_implicit_prelude 属性使用 MetaWord 语法。
no_implicit_prelude 属性只能应用于 crate 或模块。
Note
rustc忽略其他位置的用法但会发出 lint 警告。这可能在将来成为错误。
no_implicit_prelude 属性可以在一个形式上使用任意次数。
Note
rustc会对第一次之后的使用发出 lint 警告。
no_implicit_prelude 属性阻止标准库预导入、外部 crate 预导入、macro_use 预导入和工具预导入被带入模块及其后代的作用域。
Note
尽管有
#![no_implicit_prelude],rustc目前仍隐式地将某些宏带入作用域。这些宏是:
assert!cfg!cfg_select!column!compile_error!concat!concat_bytes!env!file!format_args!include!include_bytes!include_str!line!module_path!option_env!panic!stringify!unreachable!例如,这可以工作:
#![no_implicit_prelude] fn main() { assert!(true); }不要依赖此行为;它可能在未来被移除。在使用
#![no_implicit_prelude]时,始终显式地将你需要的项带入作用域。详情请参见 Rust PR #62086 和 Rust PR #139493。
no_implicit_prelude 属性不影响语言预导入。
2018 Edition differences
在 2015 版次中,
no_implicit_prelude属性不影响macro_use预导入,标准库导出的所有宏仍包含在macro_use预导入中。从 2018 版次开始,该属性确实移除了macro_use预导入。