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

Use 声明

Syntax
UseDeclarationuse UseTree ;

UseTree
      ( SimplePath? :: )? *
    | ( SimplePath? :: )? { ( UseTree ( , UseTree )* ,? )? }
    | SimplePath ( as ( IDENTIFIER | _ ) )?

use 声明_创建一个或多个本地名称绑定,与某个其他路径同义。通常,use 声明用于缩短引用模块项所需的路径。这些声明可能出现在模块中,通常在顶部。use 声明有时也称为_导入,或者,如果是公开的,则称为_重导出_。

Use 声明支持许多便捷快捷方式:

  • 使用大括号语法 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 项中允许的路径遵循 SimplePath 语法,类似于表达式中可能使用的路径。它们可以为以下内容创建绑定:

它们不能导入关联项泛型参数局部变量、带有 Self 的路径或工具属性。更多限制如下所述。

use 将为导入实体的所有命名空间创建绑定,但 self 导入仅从类型命名空间导入(如下所述)。例如,以下说明了在两个命名空间中为同一名称创建绑定:

#![allow(unused)]
fn main() {
mod stuff {
    pub struct Foo(pub i32);
}

// Imports the `Foo` type and the `Foo` constructor.
use stuff::Foo;

fn example() {
    let ctor = Foo; // Uses `Foo` from the value namespace.
    let x: Foo = ctor(123); // Uses `Foo` From the type namespace.
}
}

2018 Edition differences

在 2015 版本中,use 路径相对于 crate 根。例如:

mod foo {
    pub mod example { pub mod iter {} }
    pub mod baz { pub fn foobaz() {} }
}
mod bar {
    // Resolves `foo` from the crate root.
    use foo::example::iter;
    // The `::` prefix explicitly resolves `foo`
    // from the crate root.
    use ::foo::baz::foobaz;
}

fn main() {}

2015 版本不允许 use 声明引用外部 prelude。因此,在 2015 版本中仍然需要 extern crate 声明来在 use 声明中引用外部 crate。从 2018 版本开始,use 声明可以像 extern crate 一样指定外部 crate 依赖。

as 重命名

as 关键字可用于更改导入实体的名称。例如:

#![allow(unused)]
fn main() {
// Creates a non-public alias `bar` for the function `foo`.
use inner::foo as bar;

mod inner {
    pub fn foo() {}
}
}

大括号语法

大括号可用于路径的最后一段,以从前一段导入多个实体,或者,如果没有前一段,则从当前作用域导入。大括号可以嵌套,创建路径树,其中每个分段组在逻辑上与其父级组合以创建完整路径。

#![allow(unused)]
fn main() {
// Creates bindings to:
// - `std::collections::BTreeSet`
// - `std::collections::hash_map`
// - `std::collections::hash_map::HashMap`
use std::collections::{BTreeSet, hash_map::{self, HashMap}};
}

空大括号不导入任何内容,但会验证前导路径是否可访问。

2018 Edition differences

在 2015 版本中,路径相对于 crate 根,因此像 use {foo, bar}; 这样的导入将从 crate 根导入名称 foobar,而从 2018 版本开始,这些名称相对于当前作用域。

self 导入

关键字 self 可在大括号语法内使用,以在其自身名称下创建父实体的绑定。

mod stuff {
    pub fn foo() {}
    pub fn bar() {}
}
mod example {
    // Creates a binding for `stuff` and `foo`.
    use crate::stuff::{self, foo};
    pub fn baz() {
        foo();
        stuff::bar();
    }
}
fn main() {}

Note

self 也可用作路径的第一段。self 作为第一段和在 use 大括号内的使用在逻辑上是相同的;它表示父段的当前模块,或者如果没有父段,则表示当前模块。有关前导 self 的含义的更多信息,请参阅路径章节中的 self

self 可以作为 use 路径的最后一段出现,前面是 ::。形式为 P::self 的路径等同于 P::{self}P::self as name 等同于 P::{self as name}

mod m {
    pub enum E { V1, V2 }
}
use m::self as _; // Equivalent to `use m::{self as _};`.
use m::E::self; // Equivalent to `use m::E::{self};`.
fn main() {}

Note

有关前面路径的限制,请参阅 paths.qualifiers.mod-self.trailing

当在大括号语法内使用 self 时,大括号组前面的路径必须解析为模块枚举trait

mod m {
    pub enum E { V1, V2 }
    pub trait Tr { fn f(&self); }
}
use m::{self as _}; // OK: Modules can be parents of `self`.
use m::E::{self, V1}; // OK: Enums can be parents of `self`.
use m::Tr::{self}; // OK: Traits can be parents of `self`.
fn main() {}
struct S {}
use S::{self as _}; // ERROR: Structs cannot be parents of `self`.
fn main() {}

self 仅从父实体的类型命名空间创建绑定。例如,在以下示例中,仅导入了 foo 模块:

mod bar {
    pub mod foo {}
    pub fn foo() {}
}

// This only imports the module `foo`. The function `foo` lives in
// the value namespace and is not imported.
use bar::foo::{self};

fn main() {
    foo(); //~ ERROR `foo` is a module
}

Glob 导入

* 字符可用作 use 路径的最后一段,以导入前一段实体中的所有可导入实体。例如:

#![allow(unused)]
fn main() {
// Creates a non-public alias to `bar`.
use foo::*;

mod foo {
    fn i_am_private() {}
    enum Example {
        V1,
        V2,
    }
    pub fn bar() {
        // Creates local aliases to `V1` and `V2`
        // of the `Example` enum.
        use Example::*;
        let x = V1;
    }
}
}

项和命名导入允许在同一命名空间中遮蔽 glob 导入的名称。也就是说,如果同一命名空间中已有另一个项定义的名称,则 glob 导入将被遮蔽。例如:

#![allow(unused)]
fn main() {
// This creates a binding to the `clashing::Foo` tuple struct
// constructor, but does not import its type because that would
// conflict with the `Foo` struct defined here.
//
// Note that the order of definition here is unimportant.
use clashing::*;
struct Foo {
    field: f32,
}

fn do_stuff() {
    // Uses the constructor from `clashing::Foo`.
    let f1 = Foo(123);
    // The struct expression uses the type from
    // the `Foo` struct defined above.
    let f2 = Foo { field: 1.0 };
    // `Bar` is also in scope due to the glob import.
    let z = Bar {};
}

mod clashing {
    pub struct Foo(pub i32);
    pub struct Bar {}
}
}

Note

有关不允许遮蔽的区域,请参阅名称解析歧义

* 不能用作第一段或中间段。

* 不能用于将模块的内容导入到自身(如 use self::*;)。

2018 Edition differences

在 2015 版本中,路径相对于 crate 根,因此像 use *; 这样的导入是有效的,它意味着从 crate 根导入所有内容。这不能在 crate 根本身中使用。

下划线导入

可以使用下划线形式 use path as _ 导入项而不绑定到名称。这对于导入 trait 特别有用,以便可以使用其方法而不导入 trait 的符号,例如,如果 trait 的符号可能与另一个符号冲突。另一个示例是链接外部 crate 而不导入其名称。

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

限制

以下是有效 use 声明的限制。

使用 crate 导入当前 crate 时,必须使用 as 来定义绑定名称。

Example

#![allow(unused)]
fn main() {
use crate as root;
use crate::{self as root2};

// Not allowed:
// use crate;
// use crate::{self};
}

在宏转录器中使用 $crate 导入当前 crate 时,必须使用 as 来定义绑定名称。

Example

#![allow(unused)]
fn main() {
macro_rules! import_crate_root {
    () => {
        use $crate as my_crate;
        use $crate::{self as my_crate2};
    };
}
}

使用 self 导入当前模块时,必须使用 as 来定义绑定名称。

Example

#![allow(unused)]
fn main() {
use {self as this_module};
use self as this_module2;
use self::{self as this_module3};

// Not allowed:
// use {self};
// use self;
// use self::{self};
}

使用 super 导入父模块时,必须使用 as 来定义绑定名称。

Example

#![allow(unused)]
fn main() {
mod a {
    mod b {
        use super as parent;
        use super::{self as parent2};
        use self::super as parent3;
        use super::super as grandparent;
        use super::super::{self as grandparent2};

        // Not allowed:
        // use super;
        // use super::{self};
        // use self::super;
        // use super::super;
        // use super::super::{self};
    }
}
}

作为外部 prelude:: 不能被导入。

Example

#![allow(unused)]
fn main() {
use ::{self as root}; //~ Error
}

2018 Edition differences

在 2015 版本中,前缀 :: 指的是 crate 根,因此 use ::{self as root}; 是允许的,因为它与 use crate::{self as root}; 相同。从 2018 版本开始,:: 前缀指的是外部 prelude,不能直接导入。

#![allow(unused)]
fn main() {
use ::{self as root}; //~ Ok
}

与任何项定义一样,use 导入不能在同一模块或块中的同一命名空间中创建同名的重复绑定。

use 路径不能通过类型别名引用枚举变体。

Example

#![allow(unused)]
fn main() {
enum MyEnum {
  MyVariant
}
type TypeAlias = MyEnum;

use MyEnum::MyVariant; //~ OK
use TypeAlias::MyVariant; //~ ERROR
}