Prelude
Prelude 是一组名称,自动带入 crate 中每个模块的作用域。
这些 prelude 名称不是模块本身的一部分:它们在名称解析期间被隐式查询。例如,即使像 Box 这样的东西在每个模块中都在作用域内,您也不能将其引用为 self::Box,因为它不是当前模块的成员。
有几个不同的 prelude:
标准库 prelude
每个 crate 都有一个标准库 prelude,它由来自单个标准库模块的名称组成。
使用的模块取决于 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!之一由于[标准库 prelude]被带入作用域,并且用户编写的glob 导入将另一个带入作用域时,rustc目前允许使用panic!,即使它是有歧义的。用户编写的 glob 导入优先以解决此歧义。有关详细信息,请参阅 names.resolution.expansion.imports.ambiguity.panic-hack。
外部 prelude
在根模块中使用 extern crate 导入的外部 crate 或提供给编译器的外部 crate(如 rustc 的 --extern 标志)被添加到外部 prelude。如果使用别名导入(如 extern crate orig_name as new_name),则符号 new_name 被添加到 prelude。
core crate 始终添加到外部 prelude。
只要在 crate 根中未指定 [no_std 属性],就会添加 std crate。
2018 Edition differences
在 2015 版本中,外部 prelude 中的 crate 不能通过 use 声明引用,因此通常的做法是包含
extern crate声明以将它们带入作用域。从 2018 版本开始,use 声明可以引用外部 prelude 中的 crate,因此使用
extern crate被认为是不符合习惯的。
Note
与
rustc一起提供的其他 crate,如alloc和test,在使用 Cargo 时不会自动包含在--extern标志中。即使在 2018 版本中,也必须使用extern crate声明将它们带入作用域。#![allow(unused)] fn main() { extern crate alloc; use alloc::rc::Rc; }Cargo 仅对 proc-macro crate 将
proc_macro带入外部 prelude。
no_std 属性
*no_std 属性*导致 std crate 不被自动链接,并且[标准库 prelude]改为使用 core prelude。
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 属性将[标准库 prelude]更改为使用 core prelude 而不是 std prelude。
2018 Edition differences
在 2018 版本之前,默认将
std注入到 crate 根中。如果指定了no_std,则注入core。从 2018 版本开始,无论是否指定no_std,都不会注入到 crate 根中。
语言 prelude
语言 prelude 包含内置到语言中的类型和属性的名称。语言 prelude 始终在作用域内。
它包含以下内容:
macro_use prelude
macro_use prelude 包含通过应用于 extern crate 的 [macro_use 属性]从外部 crate 导入的宏。
工具 prelude
工具 prelude 包含类型命名空间中外部工具的工具名称。有关更多详细信息,请参阅工具属性部分。
no_implicit_prelude 属性
*no_implicit_prelude [属性]*用于阻止隐式 prelude 被带入作用域。
Example
#![allow(unused)] fn main() { // The attribute can be applied to the crate root to affect // all modules. #![no_implicit_prelude] // Or it can be applied to a module to only affect that module // and its descendants. #[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 属性阻止[标准库 prelude]、外部 prelude、macro_use prelude 和工具 prelude被带入模块及其后代的作用域。
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 属性不影响语言 prelude。
2018 Edition differences
在 2015 版本中,
no_implicit_prelude属性不影响macro_useprelude,并且从标准库导出的所有宏仍然包含在macro_useprelude 中。从 2018 版本开始,该属性确实会移除macro_useprelude。