02-作用域

作用域 — The Rust Reference

译文 · 基于 The Rust Reference

原文链接: https://doc.rust-lang.org/reference/names/scopes.html

r[names.scopes]

作用域

r[names.scopes.intro] 作用域是源文本中可以用该名称引用具名实体的区域。以下各节详细说明作用域规则与行为,它们取决于实体的种类及其声明位置。名称如何解析到实体的过程在名称解析一章中描述。更多关于用于运行析构器的“析构作用域”的信息,可见析构器一章。

r[names.scopes.items]

项作用域

r[names.scopes.items.module] 直接在模块中声明的项的名称,其作用域从模块开始延伸到模块结束。这些项也是模块的成员,可以通过从其模块出发的路径引用。

r[names.scopes.items.statement] 作为语句声明的项的名称,其作用域从该项语句所在块的开始延伸到该块的结束。

r[names.scopes.items.duplicate] 在同一模块或块内的同一命名空间中,引入与另一项重名的项是错误的。星号 glob 导入在处理重复名称与遮蔽方面有特殊行为,详见所链接章节。

r[names.scopes.items.shadow-prelude] 模块中的项可以遮蔽prelude中的项。

r[names.scopes.items.nested-modules] 外层模块的项名称不在嵌套模块的作用域内。可以使用路径引用另一模块中的项。

r[names.scopes.associated-items]

关联项作用域

r[names.scopes.associated-items.scope] 关联项没有作用域,只能通过从其关联的类型或 trait 出发的路径引用。方法也可以通过调用表达式引用。

r[names.scopes.associated-items.duplicate] 与模块或块中的项类似,在 trait 或实现中引入与该 trait 或 impl 在同一命名空间中另一项重名的项是错误的。

r[names.scopes.pattern-bindings]

模式绑定作用域

局部变量模式绑定的作用域取决于其使用位置:

r[names.scopes.pattern-bindings.let]

  • let 语句绑定的范围从紧接 let 语句之后到其声明所在块的末尾。 r[names.scopes.pattern-bindings.parameter]
  • 函数参数绑定位于函数体内。 r[names.scopes.pattern-bindings.closure]
  • 闭包参数绑定位于闭包体内。 r[names.scopes.pattern-bindings.loop]
  • for 绑定位于循环体内。 r[names.scopes.pattern-bindings.let-chains]
  • if let 与 while let 绑定在后续条件以及结果块中有效。 r[names.scopes.pattern-bindings.match-arm]
  • match 臂绑定位于match 守卫与 match 臂表达式内。 r[names.scopes.pattern-bindings.match-guard-let]
  • match 守卫 let绑定在后续守卫条件与 match 臂表达式中有效。

r[names.scopes.pattern-bindings.items] 局部变量作用域不会延伸到项声明中。

模式绑定遮蔽

r[names.scopes.pattern-bindings.shadow] 模式绑定允许遮蔽作用域中的任何名称,但下列情况除外(这些是错误):

下列示例说明局部绑定如何遮蔽项声明:

1
2
3
4
5
6
7
8
fn shadow_example() {
    // 由于作用域中尚无局部变量,这会解析到函数。
    foo(); // 打印 `function`
    let foo = || println!("closure");
    fn foo() { println!("function"); }
    // 这会解析到局部闭包,因为它遮蔽了该项。
    foo(); // 打印 `closure`
}

r[names.scopes.generic-parameters]

泛型参数作用域

r[names.scopes.generic-parameters.param-list] 泛型参数在 [GenericParams] 列表中声明。泛型参数的作用域位于声明它的项内。

r[names.scopes.generic-parameters.order-independent] 无论声明顺序如何,所有参数都在泛型参数列表的作用域内。以下展示了一些参数可在声明之前被引用的例子:

1
2
3
4
5
6
// 'b 约束在声明之前被引用。
fn params_scope<'a: 'b, 'b>() {}

## trait SomeTrait<const Z: usize> {}
// 常量 N 在 trait 约束中于声明之前被引用。
fn f<T: SomeTrait<N>, const N: usize>() {}

r[names.scopes.generic-parameters.bounds] 泛型参数也在类型约束与 where 子句的作用域内,例如:

1
2
3
4
5
6
7
## trait SomeTrait<'a, T> {}
// `SomeTrait` 的 <'a, U> 指 `bounds_scope` 的 'a 与 U 参数。
fn bounds_scope<'a, T: SomeTrait<'a, U>, U>() {}

fn where_scope<'a, T, U>()
    where T: SomeTrait<'a, U>
{}

r[names.scopes.generic-parameters.inner-items] 函数内部声明的项引用其外层作用域的泛型参数是错误的。

1
2
3
fn example<T>() {
    fn inner(x: T) {} // 错误:不能使用外层函数的泛型参数
}

泛型参数遮蔽

r[names.scopes.generic-parameters.shadow] 遮蔽泛型参数是错误的,例外是函数内声明的项允许遮蔽该函数的泛型参数名。

1
2
3
4
5
6
fn example<'a, T, const N: usize>() {
    // 函数内的项允许遮蔽作用域中的泛型参数。
    fn inner_lifetime<'a>() {} // 可以
    fn inner_type<T>() {} // 可以
    fn inner_const<const N: usize>() {} // 可以
}
1
2
3
4
5
6
trait SomeTrait<'a, T, const N: usize> {
    fn example_lifetime<'a>() {} // 错误:'a 已在使用
    fn example_type<T>() {} // 错误:T 已在使用
    fn example_const<const N: usize>() {} // 错误:N 已在使用
    fn example_mixed<const T: usize>() {} // 错误:T 已在使用
}

r[names.scopes.lifetimes]

生命周期作用域

生命周期参数在 [GenericParams] 列表与高阶 trait 约束中声明。

r[names.scopes.lifetimes.special] 'static 生命周期与占位符生命周期 '_ 具有特殊含义,不能声明为参数。

生命周期泛型参数作用域

r[names.scopes.lifetimes.generic] 常量与静态项以及常量上下文只允许 'static 生命周期引用,因此它们内部不能有其他生命周期在作用域中。关联常量确实允许引用其 trait 或实现中声明的生命周期。

高阶 trait 约束作用域

r[names.scopes.lifetimes.higher-ranked] 作为高阶 trait 约束声明的生命周期参数的作用域取决于其使用场景。

  • 作为 [TypeBoundWhereClauseItem] 时,所声明的生命周期在类型与类型约束的作用域内。
  • 作为 [TraitBound] 时,所声明的生命周期在约束类型路径的作用域内。
  • 作为 [BareFunctionType] 时,所声明的生命周期在函数参数与返回类型的作用域内。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
## trait Trait<'a>{}

fn where_clause<T>()
    // 'a 在类型与类型约束中都在作用域内。
    where for <'a> &'a T: Trait<'a>
{}

fn bound<T>()
    // 'a 在约束内的作用域中。
    where T: for <'a> Trait<'a>
{}

## struct Example<'a> {
##     field: &'a u32
## }

// 'a 在参数与返回类型中都在作用域内。
type FnExample = for<'a> fn(x: Example<'a>) -> Example<'a>;

Impl trait 限制

r[names.scopes.lifetimes.impl-trait] Impl trait 类型只能引用在函数或实现上声明的生命周期。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
## trait Trait1 {
##     type Item;
## }
## trait Trait2<'a> {}
#
## struct Example;
#
## impl Trait1 for Example {
##     type Item = Element;
## }
#
## struct Element;
## impl<'a> Trait2<'a> for Element {}
#
// 这里的 `impl Trait2` 不允许引用 'b,但允许
// 引用 'a。
fn foo<'a>() -> impl for<'b> Trait1<Item = impl Trait2<'a> + use<'a>> {
    // ...
##    Example
}

r[names.scopes.loop-label]

循环标签作用域

r[names.scopes.loop-label.scope] 循环标签可由循环表达式声明。循环标签的作用域从其声明点到循环表达式的末尾。该作用域不会延伸到项、闭包、异步块、常量参数、常量上下文,以及定义它的 for 循环的迭代器表达式中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'a: for n in 0..3 {
    if n % 2 == 0 {
        break 'a;
    }
    fn inner() {
        // 在这里使用 'a 会是错误。
        // break 'a;
    }
}

// 标签在 `while` 循环的表达式中处于作用域内。
'a: while break 'a {}         // 循环不会运行。
'a: while let _ = break 'a {} // 循环不会运行。

// 标签在定义它的 `for` 循环中不在作用域内:
'a: for outer in 0..5 {
    // 这会跳出外层循环,跳过内层循环并停止
    // 外层循环。
    'a: for inner in { break 'a; 0..1 } {
        println!("{}", inner); // 这不会运行。
    }
    println!("{}", outer); // 这也不会运行。
}

r[names.scopes.loop-label.shadow] 循环标签可以遮蔽外层作用域中的同名标签。对标签的引用指向最近的定义。

1
2
3
4
5
6
7
// 循环标签遮蔽示例。
'a: for outer in 0..5 {
    'a: for inner in 0..5 {
        // 这会终止内层循环,但外层循环继续运行。
        break 'a;
    }
}

r[names.scopes.prelude]

Prelude 作用域

r[names.scopes.prelude.intro] Prelude将实体带入每个模块的作用域。这些实体不是模块的成员,但在名称解析期间会被隐式查询。

r[names.scopes.prelude.shadow] prelude 名称可被模块中的声明遮蔽。

r[names.scopes.prelude.layers] prelude 是分层的,若包含同名实体,则一层可遮蔽另一层。prelude 可遮蔽其他 prelude 的顺序如下,靠前的条目可遮蔽靠后的条目:

  1. 外部 prelude
  2. 工具 prelude
  3. macro_use prelude
  4. 标准库 prelude
  5. 语言 prelude

r[names.scopes.macro_rules]

macro_rules 作用域

macro_rules 宏的作用域在示例宏一章中描述。其行为取决于 macro_use 与 macro_export 属性的使用。

r[names.scopes.derive]

派生宏助手属性

r[names.scopes.derive.scope] 派生宏助手属性在其对应 derive 属性所指定的项中处于作用域内。作用域从紧接 derive 属性之后延伸到该项的末尾。

r[names.scopes.derive.shadow] 助手属性会遮蔽作用域中同名的其他属性。

r[names.scopes.self]

Self 作用域

r[names.scopes.self.intro] 尽管 Self 是具有特殊含义的关键字,它与名称解析的交互方式类似于普通名称。

r[names.scopes.self.def-scope] 结构体、枚举、联合体、trait或实现定义中的隐式 Self 类型,其处理方式类似于泛型参数,并以与泛型类型参数相同的方式处于作用域内。

r[names.scopes.self.impl-scope] 实现的值命名空间中的隐式 Self 构造函数,在实现体(实现的关联项)内处于作用域中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 结构体定义中的 Self 类型。
struct Recursive {
    f1: Option<Box<Self>>
}

// 泛型参数中的 Self 类型。
struct SelfGeneric<T: Into<Self>>(T);

// 实现中的 Self 值构造函数。
struct ImplExample();
impl ImplExample {
    fn example() -> Self { // Self 类型
        Self() // Self 值构造函数
    }
}
最后修改 August 21, 2026: 更新 (76fc81a2e)