Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

预导入

预导入是一组自动带入 crate 中每个模块作用域的名称集合。

这些预导入名称不是模块本身的一部分:它们在名称解析期间被隐式查询。例如,尽管像 Box 这样的名称在每个模块中都在作用域内,你不能将其引用为 self::Box,因为它不是当前模块的成员。

存在几种不同的预导入:

标准库预导入

每个 crate 都有一个标准库预导入,由来自单个标准库模块的名称组成。

所使用的模块取决于 crate 的版次以及 no_std 属性是否应用于 crate:

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,例如 alloctest,在使用 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 是有用的。这些功能主要是动态内存分配(如 BoxVec)以及文件和网络功能(如 std::fsstd::io)。

Warning

使用 no_std 不会阻止标准库被链接。在 crate 或其依赖之一中写入 extern crate std 仍然是有效的;这将导致编译器将 std crate 链接到程序中。

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 目前仍隐式地将某些宏带入作用域。这些宏是:

例如,这可以工作:

#![no_implicit_prelude]
fn main() { assert!(true); }

不要依赖此行为;它可能在未来被移除。在使用 #![no_implicit_prelude] 时,始终显式地将你需要的项带入作用域。

详情请参见 Rust PR #62086Rust PR #139493

no_implicit_prelude 属性不影响语言预导入

2018 Edition differences

在 2015 版次中,no_implicit_prelude 属性不影响 macro_use 预导入,标准库导出的所有宏仍包含在 macro_use 预导入中。从 2018 版次开始,该属性确实移除了 macro_use 预导入。