01-语句

语句 — The Rust Reference

译文 · 基于 The Rust Reference

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

r[statement]

语句

r[statement.syntax]

Statement ->
      `;`
    | Item
    | LetStatement
    | ExpressionStatement
    | OuterAttribute* MacroInvocationSemi

r[statement.intro] 语句是块的组成部分,而块又是外层表达式或函数的组成部分。

r[statement.kind] Rust 有两类语句:声明语句与表达式语句。

r[statement.decl]

声明语句

声明语句会向包围它的语句块中引入一个或多个名字。所声明的名字可以表示新变量或新的项。

两类声明语句分别是项声明与 let 语句。

r[statement.item]

项声明

r[statement.item.intro] 项声明语句的语法形式与模块内的项声明相同。

r[statement.item.scope] 在语句块内声明项会将其作用域限制为包含该语句的块。该项不会获得规范路径,其可能声明的任何子项也不会。

r[statement.item.associated-scope] 例外是:实现所定义的关联项,只要该项以及(如适用)trait 可访问,就仍可在外层作用域中访问。除此之外,其含义与在模块内声明该项完全相同。

r[statement.item.outer-generics] 不会隐式捕获外围函数的泛型参数、参数以及局部变量。例如,inner 不能访问 outer_var。

1
2
3
4
5
6
7
fn outer() {
  let outer_var = true;

  fn inner() { /* outer_var 在此处不在作用域内 */ }

  inner();
}

r[statement.let]

let 语句

r[statement.let.syntax]

LetStatement ->
    OuterAttribute* `let` PatternNoTopAlt ( `:` Type )?
    (
          `=` Expression
        | `=` Expression _except [LazyBooleanExpression] or end with a `}`_
              `else` BlockExpressionNoInnerAttributes
    )? `;`

r[statement.let.intro] let 语句通过模式引入一组新的变量。模式之后可选地跟类型注解,然后要么结束,要么跟初始化表达式以及可选的 else 块。

r[statement.let.inference] 未给出类型注解时,编译器会推断类型;若没有足够的类型信息以确定推断,则会报错。

r[statement.let.scope] 变量声明所引入的任何变量,从声明点起直到包围块作用域结束都可见,除非被另一变量声明遮蔽。

r[statement.let.constraint] 若不存在 else 块,模式必须是不可失败的(irrefutable)。若存在 else 块,模式可以是可失败的(refutable)。

r[statement.let.behavior] 若模式不匹配(这要求它是可失败的),则执行 else 块。else 块必须始终发散(求值为从不类型)。

1
2
3
4
5
6
7
8
let (mut v, w) = (vec![1, 2, 3], 42); // 绑定可以是 mut 或 const
let Some(t) = v.pop() else { // 可失败模式需要 else 块
    panic!(); // else 块必须发散
};
let [u, v] = [v[0], v[1]] else { // 此模式不可失败,因此编译器
                                 // 会发出 lint,因为 else 块是多余的。
    panic!();
};

r[statement.expr]

表达式语句

r[statement.expr.syntax]

ExpressionStatement ->
      ExpressionWithoutBlock `;`
    | ExpressionWithBlock `;`?

r[statement.expr.intro] 表达式语句会求值一个表达式并忽略其结果。通常,表达式语句的目的是触发求值其表达式所带来的副作用。

r[statement.expr.restriction-semicolon] 仅由块表达式或控制流表达式构成的表达式,若用在允许语句的上下文中,可以省略尾随分号。这可能导致它被解析为独立语句还是另一表达式的一部分之间产生歧义;在此情况下,它会被解析为语句。

r[statement.expr.constraint-block] 当 [ExpressionWithBlock] 表达式用作语句时,其类型必须是单元类型。

1
2
3
4
5
6
7
8
## let mut v = vec![1, 2, 3];
v.pop();          // 忽略 pop 返回的元素
if v.is_empty() {
    v.push(5);
} else {
    v.remove(0);
}                 // 可以省略分号。
[1];              // 独立的表达式语句,而非索引表达式。

省略尾随分号时,结果的类型必须是 ()。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 错误:该块的类型是 i32,而非 ()
// 错误:由于默认返回类型,期望 `()`
// if true {
//   1
// }

// 正确:该块的类型是 i32
if true {
  1
} else {
  2
};

r[statement.attribute]

语句上的属性

语句接受外部属性。对语句有意义的属性是 cfg,以及lint 检查属性。

最后修改 August 21, 2026: 更新 (76fc81a2e)