路径
路径(Path)是由 :: 词法单元分隔的一个或多个路径段的序列。路径用于引用项、值、类型、宏 和 属性。
仅包含标识符段的简单路径的两个示例:
x;
x::y::z;
路径类型
简单路径
Syntax
SimplePath →
::? SimplePathSegment ( :: SimplePathSegment )*
SimplePathSegment →
IDENTIFIER | super | self | crate | $crate
#![allow(unused)]
fn main() {
use std::io::{self, Write};
mod m {
#[clippy::cyclomatic_complexity = "0"]
pub (in super) fn f1() {}
}
}
表达式中的路径
Syntax
PathInExpression →
::? PathExprSegment ( :: PathExprSegment )*
PathExprSegment →
PathIdentSegment ( :: GenericArgs )?
PathIdentSegment →
IDENTIFIER | super | self | Self | crate | $crate
GenericArgs →
< GenericArgList? >
| ( TypeList? ) ( -> TypeNoBounds )?
GenericArgList →
( GenericArg , )* GenericArg ,?
TypeList →
( Type , )* Type ,?
GenericArg →
Lifetime | Type | GenericArgsConst | GenericArgsBinding | GenericArgsBounds
GenericArgsConst →
BlockExpression
| LiteralExpression
| - LiteralExpression
| SimplePathSegment
表达式中的路径允许指定带有泛型参数的路径。它们用于表达式和模式中的各种位置。
泛型参数的开头 < 之前需要 :: 词法单元,以避免与小于运算符的歧义。这在口语中被称为“turbofish“语法。
#![allow(unused)]
fn main() {
(0..10).collect::<Vec<_>>();
Vec::<u8>::with_capacity(1024);
}
泛型参数的顺序仅限于生命周期参数,然后是类型参数,然后是 const 参数,然后是相等约束。
Const 参数必须用大括号括起来,除非它们是字面量、推断 const 或单段路径。推断 const 不能用大括号括起来。
#![allow(unused)]
fn main() {
mod m {
pub const C: usize = 1;
}
const C: usize = m::C;
fn f<const N: usize>() -> [u8; N] { [0; N] }
let _ = f::<1>(); // Literal.
let _: [_; 1] = f::<_>(); // Inferred const.
let _: [_; 1] = f::<(((_)))>(); // Inferred const.
let _ = f::<C>(); // Single segment path.
let _ = f::<{ m::C }>(); // Multi-segment path must be braced.
}
#![allow(unused)]
fn main() {
fn f<const N: usize>() -> [u8; N] { [0; _] }
let _: [_; 1] = f::<{ _ }>();
// ^ ERROR `_` not allowed here
}
Note
在泛型参数列表中,推断 const 被解析为[推断类型]inferred type,但在语义上被视为单独的 const 泛型参数。
对应于 impl Trait 类型的合成类型参数是隐式的,不能显式指定。
限定路径
Syntax
QualifiedPathInExpression → QualifiedPathType ( :: PathExprSegment )+
QualifiedPathType → < Type ( as TypePath )? >
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.
}
类型中的路径
Syntax
TypePath → ::? TypePathSegment ( :: TypePathSegment )*
TypePathSegment → PathIdentSegment ( ::? GenericArgs )?
类型路径用于类型定义、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>;
}
路径限定符
路径可以用各种前导限定符表示,以更改其解析的含义。
Note
[
use声明]对self、super、crate和$crate有额外的行为和限制。
::
以 :: 开头的路径被视为全局路径,其中路径的段从根据版本不同的位置开始解析。路径中的每个标识符必须解析为一个项。
2018 Edition differences
在 2015 版本中,标识符从“crate 根“(2018 版本中的
crate::)解析,其中包含各种不同的项,包括外部 crate、默认 crate(如std或core)以及 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 作为路径的最后一段出现时,它指的是前一段命名的实体。前面的路径必须解析为模块、枚举 或 trait。
mod m {
pub enum E { V1 }
pub trait Tr {}
pub(in crate::m::self) fn g() {} // OK: Modules can be parents of `self`.
}
type Ty = m::E::self; // OK: Enumerations can be parents of `self`.
fn f<T: m::Tr::self>() {} // OK: Traits can be parents of `self`.
fn main() { let _: Ty = m::E::V1; }
struct S;
type Ty = S::self; // ERROR: Structs cannot be parents of `self`.
fn main() {}
Note
有关
use声明中self的其他规则,请参阅 items.use.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 的类型。
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 可以在第一个 super 或 self 之后重复多次,以引用祖先模块。
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() {}