路径
一个 路径 是一个由一个或多个路径段组成的序列,这些路径段由 :: 分隔。路径用于引用 项、值、类型、宏 和 属性。
简单路径的两个示例,仅由标识符段组成
x;
x::y::z;
路径的类型
简单路径
语法
SimplePath :
::? SimplePathSegment (::SimplePathSegment)*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 (::PathExprSegment)*PathExprSegment :
PathIdentSegment (::GenericArgs)?PathIdentSegment :
标识符 |super|self|Self|crate|$crateGenericArgs :
<>
|<( GenericArg,)* GenericArg,?>GenericArg :
生命周期 | 类型 | GenericArgsConst | GenericArgsBinding | GenericArgsBoundsGenericArgsConst :
块表达式
| 字面量表达式
|-字面量表达式
| SimplePathSegmentGenericArgsBinding :
标识符 GenericArgs?=类型GenericArgsBounds :
标识符 GenericArgs?:TypeParamBounds
表达式中的路径允许指定带有泛型参数的路径。它们用于 表达式 和 模式 中的各种位置。
泛型参数的开头 < 之前需要使用 ::,以避免与小于运算符产生歧义。这在口语中被称为“turbofish”语法。
#![allow(unused)] fn main() { (0..10).collect::<Vec<_>>(); Vec::<u8>::with_capacity(1024); }
泛型参数的顺序被限制为:生命周期参数,然后是类型参数,然后是 const 参数,最后是相等性约束。
Const 参数必须用花括号包围,除非它们是 字面量 或单段路径。
与 impl Trait 类型对应的合成类型参数是隐式的,不能显式指定。
限定路径
语法
QualifiedPathInExpression :
QualifiedPathType (::PathExprSegment)+QualifiedPathType :
<类型 (asTypePath)?>QualifiedPathInType :
QualifiedPathType (::TypePathSegment)+
完全限定路径允许消除 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 (::TypePathSegment)*TypePathSegment :
PathIdentSegment (::? (GenericArgs | TypePathFn))?TypePathFn :
(TypePathFnInputs?)(->TypeNoBounds)?
类型路径用于类型定义、trait 约束、类型参数约束和限定路径中。
尽管泛型参数前允许使用 ::,但它不是必需的,因为不像 PathInExpression 那样存在歧义。
#![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 如std或core,以及 crate 顶层中的项(包括use导入)。从 2018 版本开始,以
::开头的路径从 extern 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
带大写字母“S”的 Self 用于引用正在实现或定义的当前类型。它可以在以下情况下使用
- 在 trait 定义中,它指实现该 trait 的类型。
- 在 实现 中,它指正在实现的类型。在实现 tuple 或 unit struct 时,它也指 value namespace 中的构造函数。
- 在 struct、enumeration 或 union 的定义中,它指正在定义的类型。定义不允许无限递归(必须有间接引用)。
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() {}
在第一个 super 或 self 之后可以多次重复使用 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、类型参数或类型参数上的约束),则这些关联项也没有规范路径。
模块的路径前缀是该模块的规范路径。
对于 bare 实现,它是被实现的项的规范路径,用 尖括号 (<>) 包围。
对于 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() {}