使用声明

语法

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 _;
}