使用声明
语法
UseDeclaration :
use
UseTree;
UseTree :
(SimplePath?::
)?*
| (SimplePath?::
)?{
(UseTree (,
UseTree )*,
?)?}
| SimplePath (as
( IDENTIFIER |_
) )?
使用声明 创建一个或多个与其他 路径 同义的本地名称绑定。通常,use
声明用于缩短引用模块项所需的路径。这些声明可以出现在 模块 和 代码块 中,通常位于顶部。
使用声明支持许多方便的快捷方式
- 使用类似 glob 的大括号语法
use a::b::{c, d, e::f, g::h::i};
同时绑定具有共同前缀的路径列表 - 使用
self
关键字同时绑定具有共同前缀及其共同父模块的路径列表,例如use a::b::{self, c, d::e};
- 使用语法
use p::q::r as x;
将目标名称重新绑定为新的本地名称。这也可以与最后两个功能一起使用:use a::b::{self as ab, c as abc}
。 - 使用星号通配符语法
use a::b::*;
绑定与给定前缀匹配的所有路径。 - 多次嵌套前面功能的组,例如
use a::b::{self as ab, c, d::{*, e::f}};
use
声明的示例
use std::collections::hash_map::{self, HashMap}; fn foo<T>(_: T){} fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){} fn main() { // use declarations can also exist inside of functions use std::option::Option::{Some, None}; // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), // std::option::Option::None]);' foo(vec![Some(1.0f64), None]); // Both `hash_map` and `HashMap` are in scope. let map1 = HashMap::new(); let map2 = hash_map::HashMap::new(); bar(map1, map2); }
use
可见性
与项目一样,use
声明默认情况下对包含模块是私有的。同样与项目一样,如果由 pub
关键字限定,则 use
声明可以是公共的。这样的 use
声明用于重新导出名称。因此,公共 use
声明可以将某个公共名称重定向到不同的目标定义:即使是具有私有规范路径的定义,位于不同的模块中。如果此类重定向的序列形成循环或无法明确解析,则它们表示编译时错误。
重新导出示例
mod quux { pub use self::foo::{bar, baz}; pub mod foo { pub fn bar() {} pub fn baz() {} } } fn main() { quux::bar(); quux::baz(); }
在此示例中,模块 quux
重新导出在 foo
中定义的两个公共名称。
use
路径
注意:本节尚未完成。
一些关于 use
项目有效和无效的示例
#![allow(unused_imports)] use std::path::{self, Path, PathBuf}; // good: std is a crate name use crate::foo::baz::foobaz; // good: foo is at the root of the crate mod foo { pub mod example { pub mod iter {} } use crate::foo::example::iter; // good: foo is at crate root // use example::iter; // bad in 2015 edition: relative paths are not allowed without `self`; good in 2018 edition use self::baz::foobaz; // good: self refers to module 'foo' use crate::foo::bar::foobar; // good: foo is at crate root pub mod bar { pub fn foobar() { } } pub mod baz { use super::bar::foobar; // good: super refers to module 'foo' pub fn foobaz() { } } } fn main() {}
版本差异:在 2015 版本中,
use
路径还允许访问包根目录中的项目。使用上面的示例,以下use
路径在 2015 中有效,但在 2018 中无效mod foo { pub mod example { pub mod iter {} } pub mod baz { pub fn foobaz() {} } } use foo::example::iter; use ::foo::baz::foobaz; fn main() {}
2015 版本不允许使用声明来引用 外部前奏。因此,在 2015 中,仍然需要
extern crate
声明来在使用声明中引用外部包。从 2018 版本开始,使用声明可以像extern crate
一样指定外部包依赖项。在 2018 版本中,如果范围内的项目与外部包具有相同的名称,则
use
该包名称需要前导::
以明确选择包名称。这是为了保持与未来潜在更改的兼容性。// use std::fs; // Error, this is ambiguous. use ::std::fs; // Imports from the `std` crate, not the module below. use self::std::fs as self_fs; // Imports the module below. mod std { pub mod fs {} } fn main() {}
下划线导入
可以使用下划线以 use path as _
的形式导入项目,而无需绑定到名称。这对于导入特征特别有用,这样可以在不导入特征符号的情况下使用其方法,例如,如果特征符号可能与另一个符号冲突。另一个例子是链接外部包而不导入其名称。
星号 glob 导入将以不可命名形式导入使用 _
导入的项目。
mod foo { pub trait Zoo { fn zoo(&self) {} } impl<T> Zoo for T {} } use self::foo::Zoo as _; struct Zoo; // Underscore import avoids name conflict with this item. fn main() { let z = Zoo; z.zoo(); }
唯一的、不可命名的符号是在宏扩展之后创建的,以便宏可以安全地发出对 _
导入的多个引用。例如,以下内容不应产生错误
#![allow(unused)] fn main() { macro_rules! m { ($item: item) => { $item $item } } m!(use std as _;); // This expands to: // use std as _; // use std as _; }