路径

路径 是由一个或多个路径段组成的序列,这些路径段由 :: 标记分隔。路径用于引用 条目、值、类型属性

以下是由标识符段组成的简单路径的两个示例

x;
x::y::z;

路径的类型

简单路径

语法
SimplePath :
   ::? 简单路径段 (:: 简单路径段)*

SimplePathSegment :
   标识符 | super | self | crate | $crate

简单路径用于 可见性 标记、属性use 条目。例如

#![allow(unused)]
fn main() {
use std::io::{self, Write};
mod m {
    #[clippy::cyclomatic_complexity = "0"]
    pub (in super) fn f1() {}
}
}

表达式中的路径

语法
PathInExpression :
   ::? 路径表达式段 (:: 路径表达式段)*

PathExprSegment :
   路径标识符段 (:: 泛型参数)?

PathIdentSegment :
   标识符 | super | self | Self | crate | $crate

GenericArgs :
      < >
   | < ( 泛型实参 , )* 泛型实参 ,? >

GenericArg :
   生命周期 | 类型 | GenericArgsConst | GenericArgsBinding | GenericArgsBounds

GenericArgsConst :
      BlockExpression
   | 字面量表达式
   | - 字面量表达式
   | 简单路径段

GenericArgsBinding :
   标识符 泛型参数? = 类型

GenericArgsBounds :
   标识符 泛型参数? : 类型参数边界

表达式中的路径允许指定带有泛型参数的路径。它们在 表达式模式 中的各种地方使用。

在泛型参数的开头的 < 之前需要 :: 标记,以避免与小于运算符混淆。这在口语上被称为“turbofish”语法。

#![allow(unused)]
fn main() {
(0..10).collect::<Vec<_>>();
Vec::<u8>::with_capacity(1024);
}

泛型参数的顺序限制为:生命周期参数,然后是类型参数,然后是常量参数,最后是相等性约束。

常量参数必须用花括号括起来,除非它们是 字面量 或单段路径。

对应于 impl Trait 类型的合成类型参数是隐式的,并且不能显式指定。

限定路径

语法
QualifiedPathInExpression :
   限定路径类型 (:: 路径表达式段)+

QualifiedPathType :
   < 类型 (as 类型路径)? >

QualifiedPathInType :
   限定路径类型 (:: 类型路径段)+

完全限定路径允许消除 trait 实现 的路径歧义,并允许指定 规范路径。当在类型规范中使用时,它支持使用下面指定的类型语法。

#![allow(unused)]
fn main() {
struct S;
impl S {
    fn f() { println!("S"); }
}
trait T1 {
    fn f() { println!("T1 f"); }
}
impl T1 for S {}
trait T2 {
    fn f() { println!("T2 f"); }
}
impl T2 for S {}
S::f();  // Calls the inherent impl.
<S as T1>::f();  // Calls the T1 trait function.
<S as T2>::f();  // Calls the T2 trait function.
}

类型中的路径

语法
TypePath :
   ::? 类型路径段 (:: 类型路径段)*

TypePathSegment :
   路径标识符段 (::? (泛型参数 | 类型路径函数))?

TypePathFn :
( 类型路径函数输入? ) (-> 无边界类型)?

TypePathFnInputs :
类型 (, 类型)* ,?

类型路径在类型定义、trait 边界、类型参数边界和限定路径中使用。

尽管在泛型参数之前允许使用 :: 标记,但这不是必需的,因为不像在 表达式路径 中那样存在歧义。

#![allow(unused)]
fn main() {
mod ops {
    pub struct Range<T> {f1: T}
    pub trait Index<T> {}
    pub struct Example<'a> {f1: &'a i32}
}
struct S;
impl ops::Index<ops::Range<usize>> for S { /*...*/ }
fn i<'a>() -> impl Iterator<Item = ops::Example<'a>> {
    // ...
   const EXAMPLE: Vec<ops::Example<'static>> = Vec::new();
   EXAMPLE.into_iter()
}
type G = std::boxed::Box<dyn std::ops::FnOnce(isize) -> isize>;
}

路径限定符

路径可以使用各种前导限定符来表示,以更改其解析方式的含义。

::

:: 开头的路径被认为是全局路径,其中路径的段开始从一个位置解析,该位置因版本而异。路径中的每个标识符都必须解析为一个条目。

版本差异:在 2015 版本中,标识符从“crate 根”(2018 版本中的 crate::)解析,其中包含各种不同的条目,包括外部 crate、默认 crate(例如 stdcore)以及 crate 顶层的条目(包括 use 导入)。

从 2018 版本开始,以 :: 开头的路径从 外部 prelude 中的 crate 解析。也就是说,它们后面必须跟 crate 的名称。

#![allow(unused)]
fn main() {
pub fn foo() {
    // In the 2018 edition, this accesses `std` via the extern prelude.
    // In the 2015 edition, this accesses `std` via the crate root.
    let now = ::std::time::Instant::now();
    println!("{:?}", now);
}
}
// 2015 Edition
mod a {
    pub fn foo() {}
}
mod b {
    pub fn foo() {
        ::a::foo(); // call `a`'s foo function
        // In Rust 2018, `::a` would be interpreted as the crate `a`.
    }
}
fn main() {}

self

self 解析相对于当前模块的路径。self 只能用作第一个段,前面不能有 ::

在方法体中,由单个 self 段组成的路径解析为该方法的 self 参数。

fn foo() {}
fn bar() {
    self::foo();
}
struct S(bool);
impl S {
  fn baz(self) {
        self.0;
    }
}
fn main() {}

Self

Self,首字母大写“S”,用于指代当前正在实现或定义的类型。它可以在以下情况中使用

  • trait 定义中,它指代实现该 trait 的类型。
  • 实现 中,它指代正在实现的类型。当实现元组或单元 struct 时,它也指代 值命名空间 中的构造器。
  • structenumerationunion 的定义中,它指代正在定义的类型。定义不允许无限递归(必须有一个间接层)。

Self 的作用域行为类似于泛型参数;有关更多详细信息,请参阅 Self 作用域 部分。

Self 只能用作第一个段,前面不能有 ::Self 路径不能包含泛型参数(如 Self::<i32>)。

#![allow(unused)]
fn main() {
trait T {
    type Item;
    const C: i32;
    // `Self` will be whatever type that implements `T`.
    fn new() -> Self;
    // `Self::Item` will be the type alias in the implementation.
    fn f(&self) -> Self::Item;
}
struct S;
impl T for S {
    type Item = i32;
    const C: i32 = 9;
    fn new() -> Self {           // `Self` is the type `S`.
        S
    }
    fn f(&self) -> Self::Item {  // `Self::Item` is the type `i32`.
        Self::C                  // `Self::C` is the constant value `9`.
    }
}

// `Self` is in scope within the generics of a trait definition,
// to refer to the type being defined.
trait Add<Rhs = Self> {
    type Output;
    // `Self` can also reference associated items of the
    // type being implemented.
    fn add(self, rhs: Rhs) -> Self::Output;
}

struct NonEmptyList<T> {
    head: T,
    // A struct can reference itself (as long as it is not
    // infinitely recursive).
    tail: Option<Box<Self>>,
}
}

super

路径中的 super 解析为父模块。它只能在路径的前导段中使用,可能在初始 self 段之后。

mod a {
    pub fn foo() {}
}
mod b {
    pub fn foo() {
        super::a::foo(); // call a's foo function
    }
}
fn main() {}

在第一个 superself 之后,super 可以重复多次以引用祖先模块。

mod a {
    fn foo() {}

    mod b {
        mod c {
            fn foo() {
                super::super::foo(); // call a's foo function
                self::super::super::foo(); // call a's foo function
            }
        }
    }
}
fn main() {}

crate

crate 解析相对于当前 crate 的路径。crate 只能用作第一个段,前面不能有 ::

fn foo() {}
mod a {
    fn bar() {
        crate::foo();
    }
}
fn main() {}

$crate

$crate 仅在 宏转录器 中使用,并且只能用作第一个段,前面不能有 ::$crate 将扩展为访问定义宏的 crate 顶层条目的路径,无论宏在哪个 crate 中调用。

pub fn increment(x: u32) -> u32 {
    x + 1
}

#[macro_export]
macro_rules! inc {
    ($x:expr) => ( $crate::increment($x) )
}
fn main() { }

规范路径

在模块或实现中定义的条目具有规范路径,该路径对应于其在 crate 内定义的位置。所有其他指向这些条目的路径都是别名。规范路径定义为路径前缀,后跟条目本身定义的路径段。

实现use 声明 没有规范路径,但实现定义的条目具有规范路径。在块表达式中定义的条目没有规范路径。在没有规范路径的模块中定义的条目没有规范路径。在引用没有规范路径的条目的实现中定义的关联条目,例如作为实现类型、正在实现的 trait、类型参数或类型参数的边界,没有规范路径。

模块的路径前缀是该模块的规范路径。对于裸实现,它是被实现的条目的规范路径,用 尖括号 (<>) 括起来。对于 trait 实现,它是被实现的条目的规范路径,后跟 as,然后是 trait 的规范路径,所有这些都用 尖括号 (<>) 括起来。

规范路径仅在给定的 crate 中有意义。crate 之间没有全局命名空间;条目的规范路径仅在 crate 内标识它。

// Comments show the canonical path of the item.

mod a { // crate::a
    pub struct Struct; // crate::a::Struct

    pub trait Trait { // crate::a::Trait
        fn f(&self); // crate::a::Trait::f
    }

    impl Trait for Struct {
        fn f(&self) {} // <crate::a::Struct as crate::a::Trait>::f
    }

    impl Struct {
        fn g(&self) {} // <crate::a::Struct>::g
    }
}

mod without { // crate::without
    fn canonicals() { // crate::without::canonicals
        struct OtherStruct; // None

        trait OtherTrait { // None
            fn g(&self); // None
        }

        impl OtherTrait for OtherStruct {
            fn g(&self) {} // None
        }

        impl OtherTrait for crate::a::Struct {
            fn g(&self) {} // None
        }

        impl crate::a::Trait for OtherStruct {
            fn f(&self) {} // None
        }
    }
}

fn main() {}