01-字面量表达式
字面量表达式 — The Rust Reference
7 分钟阅读
译文 · 基于 The Rust Reference
r[expr]
r[expr.syntax]
Expression ->
ExpressionWithoutBlock
| ExpressionWithBlock
ExpressionWithoutBlock ->
OuterAttribute* ExpressionWithoutBlockNoAttrs
ExpressionWithoutBlockNoAttrs ->
LiteralExpression
| PathExpression
| OperatorExpression
| GroupedExpression
| ArrayExpression
| AwaitExpression
| IndexExpression
| TupleExpression
| TupleIndexingExpression
| StructExpression
| CallExpression
| MethodCallExpression
| FieldExpression
| ClosureExpression
| AsyncBlockExpression
| ContinueExpression
| BreakExpression
| RangeExpression
| ReturnExpression
| UnderscoreExpression
| MacroInvocation
ExpressionWithBlock ->
OuterAttribute* ExpressionWithBlockNoAttrs
ExpressionWithBlockNoAttrs ->
BlockExpression
| ConstBlockExpression
| UnsafeBlockExpression
| LoopExpression
| IfExpression
| MatchExpression
r[expr.intro] 表达式可以有两种角色:它总是产生一个值,并且可能具有效果(也称为“副作用”)。
r[expr.evaluation] 表达式求值为一个值,并在求值期间产生效果。
r[expr.operands] 许多表达式包含子表达式,称为该表达式的操作数。
r[expr.behavior] 每种表达式的含义规定了若干事项:
r[expr.structure] 如此,表达式的结构决定了执行的结构。块只是另一种表达式,因此块、语句、表达式以及块可以彼此递归嵌套到任意深度。
注意 我们为表达式的操作数命名以便讨论,但这些名称并不稳定,可能会更改。
r[expr.precedence]
Rust 运算符和表达式的优先级按如下顺序从强到弱排列。同一优先级的二元运算符按其结合性所给出的顺序分组。
| 运算符/表达式 | 结合性 |
|---|---|
| [路径][expr.path] | |
| [方法调用][expr.method] | |
| [字段表达式][expr.field] | 从左到右 |
| [函数调用][expr.call],[数组索引][expr.array.index] | |
[?][expr.try] | |
一元 [-][expr.negate] [!][expr.negate] [*][expr.deref] [借用][expr.operator.borrow] | |
[as][expr.as] | 从左到右 |
[*][expr.arith-logic] [/][expr.arith-logic] [%][expr.arith-logic] | 从左到右 |
[+][expr.arith-logic] [-][expr.arith-logic] | 从左到右 |
[<<][expr.arith-logic] [>>][expr.arith-logic] | 从左到右 |
[&][expr.arith-logic] | 从左到右 |
[^][expr.arith-logic] | 从左到右 |
[|][expr.arith-logic] | 从左到右 |
[==][expr.cmp] [!=][expr.cmp] [<][expr.cmp] [>][expr.cmp] [<=][expr.cmp] [>=][expr.cmp] | 需要括号 |
[&&][expr.bool-logic] | 从左到右 |
[||][expr.bool-logic] | 从左到右 |
[..][expr.range] [..=][expr.range] | 需要括号 |
[=][expr.assign] [+=][expr.compound-assign] [-=][expr.compound-assign] [*=][expr.compound-assign] [/=][expr.compound-assign] [%=][expr.compound-assign][ &=][expr.compound-assign] [|=][expr.compound-assign] [^=][expr.compound-assign] [<<=][expr.compound-assign] [>>=][expr.compound-assign] | 从右到左 |
[return][expr.return] [break][expr.loop.break] [闭包][expr.closure] |
r[expr.operand-order]
r[expr.operand-order.default] 下列表达式都以相同方式求值其操作数,如列表之后所述。其他表达式要么没有操作数,要么按各自页面所述有条件地求值操作数。
r[expr.operand-order.operands-before-primary] 这些表达式的操作数在应用该表达式的效果之前求值。接受多个操作数的表达式按源代码中书写的顺序从左到右求值。
注意 哪些子表达式是某表达式的操作数,由上一节的表达式优先级决定。
例如,两次 next 方法调用总是按相同顺序进行:
| |
注意 由于这是递归应用的,这些表达式也从最内层到最外层求值,在没有更内层的子表达式之前会忽略兄弟表达式。
r[expr.place-value]
r[expr.place-value.intro] 表达式分为两大类:位置表达式和值表达式;还有第三类较小的范畴,称为赋值目标表达式。在每个表达式内部,操作数同样可能出现在位置上下文或值上下文中。表达式的求值既取决于它自身的类别,也取决于它所处的上下文。
r[expr.place-value.place-memory-location] 位置表达式是表示内存位置的表达式。
r[expr.place-value.place-expr-kinds]
这些表达式是引用局部变量的路径、静态变量、解引用(*expr)、数组索引表达式(expr[expr])、字段引用(expr.f)以及圆括号括起的位置表达式。
r[expr.place-value.value-expr-kinds] 所有其他表达式都是值表达式。
r[expr.place-value.value-result] 值表达式是表示实际值的表达式。
r[expr.place-value.place-context] 下列上下文是位置表达式上下文:
let 语句的初始化器。if let、match 或 while let 表达式的被检视表达式。注意 历史上,位置表达式曾被称为 lvalue(左值),值表达式曾被称为 rvalue(右值)。
r[expr.place-value.assignee] 赋值目标表达式是出现在赋值表达式左操作数中的表达式。具体而言,赋值目标表达式是:
r[expr.place-value.parenthesis] 赋值目标表达式内部允许任意加括号。
r[expr.move]
r[expr.move.intro] 当位置表达式在值表达式上下文中被求值,或在模式中按值绑定,它表示该内存位置_中_所持有的值。
r[expr.move.copy]
若该值的类型实现了 Copy,则该值会被复制。
r[expr.move.requires-sized]
在其余情况下,若该类型是 Sized,则可能可以移动该值。
r[expr.move.movable-place] 只有下列位置表达式可以从中移出:
r[expr.move.deinitialization] 从求值为局部变量的位置表达式中移出之后,该位置被去初始化,在重新初始化之前不能再读取。
r[expr.move.place-invalid] 在所有其他情况下,试图在值表达式上下文中使用位置表达式都是错误。
r[expr.mut]
r[expr.mut.intro]
位置表达式要被赋值、可变借用、隐式可变借用,或绑定到含 ref mut 的模式,它必须是_可变的_。我们称这些为可变位置表达式。相对地,其他位置表达式称为不可变位置表达式。
r[expr.mut.valid-places] 下列表达式可以成为可变位置表达式上下文:
static 项。*mut T 指针的解引用。&mut T 的变量或其字段的解引用。注意:这是下一条规则要求的例外。DerefMut 的类型的解引用:这进而要求被解引用的值在可变位置表达式上下文中求值。IndexMut 的类型的数组索引:这会在可变位置表达式上下文中求值被索引的值,但不求值索引。r[expr.temporary]
当在大多数位置表达式上下文中使用值表达式时,会创建一个未命名的临时内存位置,并初始化为该值。表达式求值为该位置,除非它被提升为 static。该临时值的drop 作用域通常是包围语句的末尾。
r[expr.super-macros]
r[expr.super-macros.intro] 某些内置宏可能创建其作用域可被延长的临时值。这些临时值是超临时值,这些宏是超宏。这些宏的调用是超宏调用表达式。这些宏的实参可能是超操作数。
注意 当超宏调用表达式是延长表达式时,其超操作数是延长表达式,且超临时值的作用域会被延长。见 [destructors.scope.lifetime-extension.exprs]。
r[expr.super-macros.format_args]
format_args!r[expr.super-macros.format_args.super-operands]
除格式字符串实参外,传给 format_args! 的所有实参都是超操作数。
| |
r[expr.super-macros.format_args.super-temporaries]
format_args! 的超操作数会被隐式借用,因此是位置表达式上下文。当以值表达式作为实参传入时,会创建一个超临时值。
| |
对 format_args! 的调用展开有时会创建其他内部超临时值。
| |
| |
注意
format_args!何时会或不创建内部临时值的细节目前尚未规定。
r[expr.super-macros.pin]
pin!r[expr.super-macros.pin.super-operands]
pin! 的实参是超操作数。
| |
r[expr.super-macros.pin.super-temporaries]
pin! 的实参是值表达式上下文,并创建一个超临时值。
| |
r[expr.implicit-borrow]
r[expr.implicit-borrow-intro]
某些表达式会通过隐式借用把一个表达式当作位置表达式。例如,可以直接比较两个不定大小的切片是否相等,因为 == 运算符会隐式借用其操作数:
| |
r[expr.implicit-borrow.application] 下列表达式中可能发生隐式借用:
*)的操作数。format_args! 的实参,格式字符串除外。r[expr.overload]
下列许多运算符和表达式也可以通过 std::ops 或 std::cmp 中的 trait 为其他类型重载。这些 trait 在 core::ops 和 core::cmp 中也以相同名称存在。
r[expr.attr]
r[expr.attr.restriction] 表达式之前的外部属性仅在少数特定情况下允许:
r[expr.attr.never-before] 它们从不允许出现在下列位置之前:
字面量表达式 — The Rust Reference
路径表达式 — The Rust Reference
块表达式 — The Rust Reference
运算符表达式 — The Rust Reference
分组表达式 — The Rust Reference
数组与索引表达式 — The Rust Reference
元组与索引表达式 — The Rust Reference
结构体表达式 — The Rust Reference
调用表达式 — The Rust Reference
方法调用表达式 — The Rust Reference
字段访问表达式 — The Rust Reference
闭包表达式 — The Rust Reference
循环表达式 — The Rust Reference
区间表达式 — The Rust Reference
if 表达式 — The Rust Reference
match 表达式 — The Rust Reference
return 表达式 — The Rust Reference
await 表达式 — The Rust Reference
下划线表达式 — The Rust Reference