6. Expressions¶
Syntax
Expression
::=ExpressionWithBlock
|ExpressionWithoutBlock
ExpressionWithBlock
::=OuterAttributeOrDoc
* (AsyncBlockExpression
|BlockExpression
|ConstBlockExpression
|IfExpression
|IfLetExpression
|LoopExpression
|MatchExpression
|UnsafeBlockExpression
|NamedBlockExpression
)ExpressionWithoutBlock
::=OuterAttributeOrDoc
* (ArrayExpression
|AwaitExpression
|BreakExpression
|CallExpression
|ClosureExpression
|ContinueExpression
|FieldAccessExpression
|IndexExpression
|LiteralExpression
|MethodCallExpression
|MacroInvocation
|OperatorExpression
|ParenthesizedExpression
|PathExpression
|RangeExpression
|ReturnExpression
|StructExpression
|TupleExpression
|UnderscoreExpression
)ExpressionList
::=Expression
(,Expression
)* ,?Operand
::=Expression
LeftOperand
::=Operand
RightOperand
::=Operand
6:1
A SubjectExpression
is any expression in category Expression
, except
StructExpression
.
6:2
A SubjectLetExpression
is any expression in category
SubjectExpression
, except LazyBooleanExpression
.
Legality Rules
6:3 An expression is a construct that produces a value, and may have side effects at run-time.
6:4 An expression-with-block is an expression whose structure involves a block expression.
6:5 An expression-without-block is an expression whose structure does not involve a block expression.
6:6 An operand is an expression nested within an expression.
6:7 A left operand is an operand that appears on the left-hand side of a binary operator.
6:8 A right operand is an operand that appears on the right-hand side of a binary operator.
6:9 A subject expression is an expression that controls for loops, if expressions, and match expressions.
6:10 A subject let expression is an expression that controls if let expressions and while let loops.
Dynamic Semantics
6:11 Evaluation is the process by which an expression achieves its runtime effects.
6.1. Expression Classification¶
6.1.1. Assignee Expressions¶
Legality Rules
6.1.1:1 An assignee expression is an expression that appears as the left operand of an assignment expression. The following expressions are assignee expressions:
6.1.1:2 Place expressions,
6.1.1:3 Underscore expressions,
6.1.1:4 Array expressions of assignee expressions,
6.1.1:5 Struct expressions of assignee expressions.
6.1.1:6 Tuple expressions of assignee expressions,
6.1.1:7 Tuple struct call expressions of assignee expressions,
6.1.1:8 Parenthesized expressions are allowed to appear anywhere in assignee expressions.
6.1.2. Constant Expressions¶
Legality Rules
6.1.2:1 A constant expression is an expression that can be evaluated statically. The following constructs are constant expressions as long as their operands are also constant expressions and do not involve types that require destruction:
6.1.2:2 Arithmetic expressions of scalar types,
6.1.2:3 Array expressions,
6.1.2:4 Assignment expressions,
6.1.2:5 Bit expressions of scalar types,
6.1.2:6 Block expressions,
6.1.2:7 Call expressions where the callee is a constant function,
6.1.2:8 Closure expressions that do not capture,
6.1.2:9 Comparison expressions of scalar types,
6.1.2:10 Compound assignment expressions,
6.1.2:11 Constant parameters,
6.1.2:12 Dereference expressions when the operand is not of a raw pointer type,
6.1.2:13 Expression statements,
6.1.2:14 Field access expressions that do not invoke the
core::ops::Deref
trait,6.1.2:15 If expressions,
6.1.2:16 If let expressions,
6.1.2:17 Immutable borrow expressions where the borrowed type is not subject to interior mutability.
6.1.2:18 Index expressions,
6.1.2:19 Infinite loop expressions,
6.1.2:20 Lazy boolean expressions of scalar types,
6.1.2:21 Let statements,
6.1.2:22 Literal expressions,
6.1.2:23 Match expressions,
6.1.2:24 Method call expressions where the callee is a constant function or do not invoke the
core::ops::Deref
trait,6.1.2:25 Negation expressions of scalar types,
6.1.2:26 Parenthesized expressions,
6.1.2:27 Path expressions that resolve to associated constants, constants, constant parameters, functions, statics, tuple structs, and unit structs,
6.1.2:28 Range expressions,
6.1.2:29 Shared borrows that do not involve types with interior mutability,
6.1.2:30 Struct expressions,
6.1.2:31 Tuple expressions,
6.1.2:32 Type cast expressions that are not pointer-to-address casts, function-pointer-to-address casts, and unsized coercions that involve a trait object type,
6.1.2:33 Unsafe block expressions,
6.1.2:34 While let loop expressions,
6.1.2:35 While loop expressions.
6.1.2:36
An expression is not considered a constant expression when it
explicitly invokes an associated trait function or uses
arithmetic operators of non-builtin types that invoke
core::ops
traits.
6.1.2:37 An arithmetic expression that operates with floating-point values is not considered a constant expression when it appears inside the function body of a constant function.
6.1.2:38 It is a static error if the size operand of an array repetition constructor or an array type depends on generic parameters.
6.1.2:39 A constant context is a construct that requires a constant expression. The following constructs are constant contexts:
6.1.2:40 The constant initializer of an associated constant or a constant,
6.1.2:41 The constant argument for a constant parameter,
6.1.2:42 The default value of a constant parameter,
6.1.2:43 The discriminant initializer of an enum variant,
6.1.2:44 The size operand of an array repetition constructor,
6.1.2:45 The size operand of an array type,
6.1.2:46 The static initializer of a static.
6.1.2:47 The block expression of a const block expression.
6.1.2:48 It is a static error to create a mutable reference in a constant context.
6.1.2:49
An invocation of the core::ptr::addr_of
macro expands to a
constant expression allowed in any constant context and
constant function, subject to the same restrictions as a
immutable borrow expression.
6.1.2:50
An invocation of the core::panic
macro expands to a
constant expression allowed in any constant context and
constant function, as long as the macro is either invoked without
arguments, or with a single string literal that does not
capture formatting arguments.
6.1.2:51 A constant expression is evaluated statically whenever its value is needed.
6.1.2:52 The evaluation of a constant expression that results in arithmetic overflow panics.
6.1.2:53
It is a static error if a constant expression either panics or
control reaches the invocation of macro core::panic
.
6.1.2:54 It is a static error if the evaluation of a constant expression results in a value that is unaligned.
Dynamic Semantics
6.1.2:55 The invocation of a constant function follows the dynamic semantics of a non-constant function invocation.
6.1.3. Diverging Expressions¶
Legality Rules
6.1.3:1 A diverging expression is an expression whose evaluation causes program flow to diverge from the normal evaluation order.
6.1.3:2 Diverging expressions are:
6.1.3:3 Break expressions,
6.1.3:4 Return expressions,
6.1.3:5 Loop expressions that are not the target of any break expressions,
6.1.3:6 Call expressions and method call expressions if the return type of the call operand is the never type,
6.1.3:7 Invocations of the
core::panic
macro,6.1.3:8 Any expression whose evaluation requires the evaluation of a diverging subexpression on all reachable control flow paths.
6.1.4. Place Expressions¶
Legality Rules
6.1.4:1 A place expression is an expression that represents a memory location. The following expressions are place expressions:
6.1.4:2 Dereference expressions,
6.1.4:3 Field access expressions,
6.1.4:4 Index expressions,
6.1.4:5 Parenthesized expressions where the operand is a place expression,
6.1.4:6 Path expressions that resolve to a static or a variable.
6.1.4:7 A temporary.
6.1.4:8 A mutable place expression is a place expression whose memory location can be modified. The following place expressions are mutable place expressions:
6.1.4:9 A dereference expression whose operand‘s type implements the
core::ops::DerefMut
trait,6.1.4:10 A dereference expression whose operand‘s type is a mutable raw pointer type,
6.1.4:11 A dereference expression whose operand‘s type is a mutable reference type,
6.1.4:12 A field access expression where the container operand is a mutable place expression,
6.1.4:13 An index expression whose type implements the
core::ops::IndexMut
trait,6.1.4:14 Parenthesized expressions where the operand is a mutable place expression,
6.1.4:15 A path expression that resolves to a mutable static,
6.1.4:16 A path expression that resolves to a mutable variable that is not currently borrowed,
6.1.4:17 A temporary.
6.1.4:18 An immutable place expression is a place expression whose memory location cannot be modified. All place expressions that are not mutable place expressions are immutable place expressions.
6.1.4:19 A place expression context is a construct that may evaluate its operand as a memory location.
6.1.4:20 The following constructs are place expression contexts:
6.1.4:21 The assignee operand of an assignment expression or a compound assignment expression,
6.1.4:22 The operand of a borrow expression,
6.1.4:23 The operand of a dereference expression,
6.1.4:24 The container operand of a field access expression,
6.1.4:25 The initialization expression of a let statement,
6.1.4:26 The operand of an implicit borrow,
6.1.4:27 The indexed operand of an index expression,
6.1.4:28 The subject let expression of an if let expression or a while let loop expression,
6.1.4:29 The subject expression of a match expression,
6.1.4:30 The base initializer of a struct expression.
6.1.4:31 A mutable place expression context is a place expression context that may evaluate its operand as a mutable memory location. The following constructs are mutable place expression contexts:
6.1.4:32 The indexed operand of an index expression if evaluated in a mutable place expression context,
6.1.4:33 The assignee operand of an assignment expression or a compound assignment expression,
6.1.4:34 The operand of a mutable borrow expression,
6.1.4:35 The operand of a dereference expression if evaluated in a mutable place expression context,
6.1.4:36 The container operand of field access expression if evaluated in a mutable place expression context,
6.1.4:37 The subject let expression of an if let expression or a while let loop expression,
6.1.4:38 The operand of a mutable implicit borrow,
6.1.4:39 The initialization expression of a let statement,
6.1.4:40 The subject expression of a match expression,
6.1.4:41 A place expression that is evaluated in a value expression context or bound by value in a pattern denotes the value held in the memory location of the place expression. Such an evaluation is subject to passing conventions.
6.1.5. Value Expressions¶
Legality Rules
6.1.5:1 A value expression is an expression that represents a value. All expressions that are not place expressions are value expressions.
6.1.5:2 A value expression context is an expression context that is not a place expression context.
6.1.5:3 The evaluation of a value expression in a place expression context shall evaluate the value expression as a temporary and then use the temporary in the place expression context.
6.2. Literal Expressions¶
Syntax
LiteralExpression
::=Literal
Legality Rules
6.2:1 A literal expression is an expression that denotes a literal.
6.2:2 The type of a literal expression is the type of the corresponding literal.
6.2:3 The value of a literal expression is the value of the corresponding literal.
Dynamic Semantics
6.2:4 The evaluation of a literal expression has no effect.
Examples
5
'a'
"hello"
6.3. Path Expressions¶
Syntax
PathExpression
::=UnqualifiedPathExpression
|QualifiedPathExpression
Legality Rules
6.3:1 A path expression is an expression that denotes a path.
6.3:2 A path expression shall resolve to either a constant parameter, a constant, a function, a static, a tuple enum variant, a tuple struct, a unit enum variant, a unit struct, or a variable.
6.3:3 A path expression that resolves to a mutable static shall require unsafe context.
6.3:4 The type of a path expression is the type of the entity that it resolved to.
6.3:5 The value of a path expression is the entity that it resolved to.
Examples
globals::STATIC_VARIABLE
Vec::<i32>::push
6.4. Block Expressions¶
Syntax
BlockExpression
::= {InnerAttributeOrDoc
*StatementList
}StatementList
::=Statement
*Expression
?
Legality Rules
6.4:1 A block expression is an expression that sequences expressions and statements.
6.4:2 A tail expression is the last expression within a block expression.
6.4:3
When the remaining lexical elements of a StatementList
match either
an Expression
or Statement
they are interpreted as an Expression
.
6.4:4 The type of a block expression is determined as follows:
6.4:5 If the block expression contains at least one break expression and has a tail expression, then the type is the unified type of the break types of all break expressions and the type of the tail expression.
6.4:6 Otherwise, if the block expression contains at least one break expression, then the type is the unified type of the break types of all break expressions.
6.4:7 Otherwise, if the block expression has a tail expression, then the type is the type of the tail expression.
6.4:9 The value of a block expression is determined as follows:
6.4:10 If the block expression contains at least one break expression and a break expression broke out the block expression, then the value is the break value of the break expression that broke out of the block expression.
6.4:11 Otherwise, if the block expression has a tail expression, then the value is the value of the tail expression.
6.4:12 Otherwise the value is the unit value.
Dynamic Semantics
6.4:13 The evaluation of a block expression proceeds as follows:
6.4:14 Each statement is executed in declarative order.
6.4:15 The tail expression is evaluated.
Examples
{
fn_call();
42
}
6.4.1. Async Blocks¶
Syntax
AsyncBlockExpression
::= async move?BlockExpression
Legality Rules
6.4.1:1
An async block expression is a block expression that is specified
with keyword async
and encapsulates behavior which is executed in
an asynchronous manner.
6.4.1:2 An async block expression denotes a new async control flow boundary.
6.4.1:3 An async block expression is subject to capturing.
6.4.1:4
The type of an async block expression is a unique anonymous type
that implement the core::future::Future
trait.
6.4.1:5 The value of an async block expression is a value of the async block expression‘s type.
Dynamic Semantics
6.4.1:6 The evaluation of an async block expression produces a value of the type of the async block expression that captures the capture targets of the async block expression.
Examples
async {
42
}
6.4.2. Const Blocks¶
Syntax
ConstBlockExpression
::= constBlockExpression
Legality Rules
6.4.2:1
A const block expression is a block expression that is specified
with keyword const
and encapsulates behavior which is evaluated
statically.
6.4.2:2 An const block expression denotes a new control flow boundary.
6.4.2:3 The block expression of a const block expression shall be a constant expression.
6.4.2:4 The type of a const block expression is the type of the containing block expression.
6.4.2:5 The value of a const block expression is the value of the contained block expression.
Examples
const {
42
}
6.4.3. Named Blocks¶
Syntax
NamedBlockExpression
::=Label
BlockExpression
Legality Rules
6.4.3:1 A named block expression is a block expression with a label.
6.4.3:2 The type of the named block expression is the type of its block expression.
6.4.3:3 The value of the named block expression is the value of its block expression.
Examples
'block: {
break 'block 1;
3
}
6.4.4. Unsafe Blocks¶
Syntax
UnsafeBlockExpression
::= unsafeBlockExpression
Legality Rules
6.4.4:1
An unsafe block expression is a block expression that is specified
with keyword unsafe
.
6.4.4:2 An unsafe block expression allows unsafety.
6.4.4:3 The type of the unsafe block expression is the type of its block expression.
6.4.4:4 The value of the unsafe block expression is the value of its block expression.
Dynamic Semantics
6.4.4:5 The evaluation of an unsafe block expression evaluates its block expression.
Examples
unsafe {
unsafe_fn_call()
}
6.5. Operator Expressions¶
Syntax
OperatorExpression
::=ArithmeticExpression
|AssignmentExpression
|BitExpression
|BorrowExpression
|ComparisonExpression
|CompoundAssignmentExpression
|DereferenceExpression
|ErrorPropagationExpression
|LazyBooleanExpression
|NegationExpression
|TypeCastExpression
Legality Rules
6.5:1 An operator expression is an expression that involves an operator.
6.5.1. Borrow Expression¶
Syntax
BorrowExpression
::= & mut?Operand
Legality Rules
6.5.1:1 A borrow expression is an expression that borrows the value of its operand and creates a reference to the memory location of its operand.
6.5.1:2
An immutable borrow expression is a borrow expression that lacks
keyword mut
.
6.5.1:3
A mutable borrow expression is a borrow expression that has
keyword mut
.
6.5.1:4 When the operand of a borrow expression is a place expression, the borrow expression produces a reference to the memory location indicated by the operand. The memory location is placed in a borrowed state, or simply borrowed.
6.5.1:5 The type of a borrow expression is determined as follows:
6.5.1:6 If the borrow expression denotes a shared reference, then the type is
&T
, whereT
is the type of the operand.6.5.1:7 If the borrow expression denotes a mutable reference, then the type is
&mut T
, whereT
is the type of the operand.
6.5.1:8 The value of a borrow expression is the address of its operand.
6.5.1:9
It is a static error if a borrow expression would create an unaligned
reference to a field in an abstract data type subject to
attribute repr
.
Dynamic Semantics
6.5.1:10 The evaluation of a borrow expression evaluates its operand.
Examples
let mut answer = 42;
6.5.1:11 Mutable borrow.
let ref_answer = &mut answer;
6.5.2. Dereference Expression¶
Syntax
DereferenceExpression
::= *Operand
Legality Rules
6.5.2:1 A dereference expression is an expression that obtains the pointed-to memory location of its operand.
6.5.2:2 When the operand of a dereference expression is of a pointer type, the dereference expression denotes the pointed-to memory location of the operand, or the dereference of the operand.
6.5.2:3 The dereference is assignable when the dereference expression is a mutable place expression.
6.5.2:4 Dereferencing a raw pointer shall require unsafe context.
6.5.2:5
If the context of a dereference expression is an
immutable place expression context, then the dereference expression
is equivalent to expression *core::ops::Deref::deref(&operand)
.
6.5.2:6
If the context of a dereference expression is a
mutable place expression context, then the dereference expression
is equivalent to expression
*core::ops::DerefMut::deref_mut(&mut operand)
.
6.5.2:7 The type of a dereference expression is determined as follows:
6.5.2:8 If the type of the operand is
&mut T
,&T
,*mut T
, or*const T
, then the type isT
.6.5.2:9 Otherwise the type is associated type
core::ops::Deref::Target
.
6.5.2:10 The value of a dereference expression is determined as follows:
6.5.2:11 If the type of the operand is
&mut T
,&T
,*mut T
, or*const T
, then the value is the pointed-to value.6.5.2:12 Otherwise the value is the result of evaluating expression
*core::ops::Deref::deref(&operand)
or expression*core::ops::DerefMut::deref_mut(&mut operand)
respectively.
Dynamic Semantics
6.5.2:13 The evaluation of a dereference expression evaluates its operand.
Undefined Behavior
6.5.2:14 It is undefined behavior to dereference a raw pointer that is either dangling or unaligned.
Examples
6.5.2:15
See 6.5.1:11 for the declaration of ref_answer
.
let deref_asnwer = *ref_answer;
6.5.3. Error Propagation Expression¶
Syntax
ErrorPropagationExpression
::=Operand
?
Legality Rules
6.5.3:1 An error propagation expression is an expression that either evaluates to a value of its operand or returns a value to the enclosing control flow boundary.
6.5.3:2 An error propagation expression shall appear within a control flow boundary.
6.5.3:3
The type of an error propagation expression is associated type
core::ops::Try::Output
.
6.5.3:4 The value of an error propagation expression is determined as follows:
6.5.3:5 If the evaluation of the error propagation expression executed
core::ops::Try::branch
, then the value is the value of thecore::ops::ControlFlow::Continue
variant.6.5.3:6 Otherwise control flow is returned to the end of the enclosing control flow boundary.
Dynamic Semantics
6.5.3:7 The evaluation of an error propagation expression of the form
expression?
6.5.3:8 is equivalent to the evaluation the following expression:
match core::ops::Try::branch(expression) {
core::ops::ControlFlow::Continue(value) =>
value,
core::ops::ControlFlow::Break(value) =>
core::ops::FromResidual::from_residual(value),
}
Examples
fn try_to_parse() -> Result<i32, ParseIntError> {
"42".parse()?
}
fn try_some() -> Option<i32> {
let val = Some(42)?;
Some(val)
}
6.5.4. Negation Expression¶
Syntax
NegationExpression
::=NegationOperator
Operand
NegationOperator
::=BitwiseNegationOperator
|SignNegationOperator
BitwiseNegationOperator
::= !SignNegationOperator
::= -
Legality Rules
6.5.4:1 A negation expression is an expression that negates its operand.
6.5.4:2
The type of the operand of a negation expression with a
BitwiseNegationOperator
shall implement the core::ops::Not
trait.
6.5.4:3
The type of a negation expression with a BitwiseNegationOperator
is associated type core::ops::Not::Output
.
6.5.4:4
The value of a negation expression with a BitwiseNegationOperator
is the result of core::ops::Not::not(operand)
.
6.5.4:5
The type of the operand of a negation expression with a
SignNegationOperator
shall implement the core::ops::Neg
trait.
6.5.4:6
The type of a negation expression with a SignNegationOperator
shall be associated type core::ops::Neg::Output
.
6.5.4:7
The value of a negation expression with a SignNegationOperator
is
the result of core::ops::Neg::neg(operand)
.
Dynamic Semantics
6.5.4:8
The evaluation of a negation expression with a
BitwiseNegationOperator
proceeds as follows:
6.5.4:9 The operand is evaluated.
6.5.4:10 If the type of the operand is an integer type, then the negation expression evaluates to the bitwise negation of the operand.
6.5.4:11 If the type of the operand is
bool
, then the result is computed as follows, depending on the value of the operand:
6.5.4:12
Operand
Result
6.5.4:13
true
false
6.5.4:14
false
true
6.5.4:15 If the type of operand is neither an integer type nor
bool
, thencore::ops::Not::not(operand)
is invoked.
6.5.4:16
The evaluation of a negation expression with a
SignNegationOperator
proceeds as follows:
6.5.4:17 The operand is evaluated.
6.5.4:18 If the type of the operand is an integer type, then the negation expression evaluates to the value of the operand, with its sign inverted. If the result of the negation expression does not fit within the range of the operand type, then arithmetic overflow occurs.
6.5.4:19 If the type of the operand is a floating-point type, then the negation expression evaluates to the value of the operand, with its sign inverted. No arithmetic overflow is possible.
6.5.4:20 If the type of the operand is neither an integer type nor a floating-point type, then
core::ops::Neg::neg(operand)
is invoked.
Examples
6.5.4:21 Sign negation.
-42
6.5.4:22 Bitwise negation.
!42
6.5.4:23 Logical negation.
!false
6.5.5. Arithmetic Expressions¶
Syntax
ArithmeticExpression
::=AdditionExpression
|DivisionExpression
|MultiplicationExpression
|RemainderExpression
|SubtractionExpression
AdditionExpression
::=LeftOperand
+RightOperand
DivisionExpression
::=LeftOperand
/RightOperand
MultiplicationExpression
::=LeftOperand
*RightOperand
RemainderExpression
::=LeftOperand
%RightOperand
SubtractionExpression
::=LeftOperand
-RightOperand
Legality Rules
6.5.5:1 An arithmetic expression is an expression that computes a value from two operands using arithmetic.
6.5.5:2 An addition expression is an arithmetic expression that uses addition.
6.5.5:3
The type of the left operand of an addition expression shall
implement the core::ops::Add
trait with the type of the
right operand as the trait implementation type parameter.
6.5.5:4
The type of an addition expression is associated type
core::ops::Add::Output
.
6.5.5:5
The value of an addition expression is the result of
core::ops::Add::add(left_operand, right_operand)
.
6.5.5:6 A division expression is an arithmetic expression that uses division.
6.5.5:7
The type of the left operand of a division expression shall
implement the core::ops::Div
trait where the type of the
right operand is the trait implementation type parameter.
6.5.5:8
The type of a division expression is associated type
core::ops::Div::Output
.
6.5.5:9
The value of a division expression is the result of
core::ops::Div::div(left_operand, right_operand)
.
6.5.5:10 A multiplication expression is an arithmetic expression that uses multiplication.
6.5.5:11
The type of the left operand of a multiplication expression
shall implement the core::ops::Mul
trait where the type of the
right operand is the trait implementation type parameter.
6.5.5:12
The type of a multiplication expression is associated type
core::ops::Mul::Output
.
6.5.5:13
The value of a multiplication expression is the result of
core::ops::Mul::mul(left_operand, right_operand)
.
6.5.5:14 A remainder expression is an arithmetic expression that uses remainder division.
6.5.5:15
The type of the left operand of a remainder expression shall
implement the core::ops::Rem
trait where the type of the
right operand is the trait implementation type parameter.
6.5.5:16
The type of a remainder expression is associated type
core::ops::Rem::Output
.
6.5.5:17
The value of a remainder expression is the result of
core::ops::Rem::rem(left_operand, right_operand)
.
6.5.5:18 A subtraction expression is an arithmetic expression that uses subtraction.
6.5.5:19
The type of the left operand of a subtraction expression shall
implement the core::ops::Sub
trait where the type of the
right operand is the trait implementation type parameter.
6.5.5:20
The type of a subtraction expression is associated type
core::ops::Sub::Output
.
6.5.5:21
The value of a subtraction expression is the result of
core::ops::Sub::sub(left_operand, right_operand)
.
Dynamic Semantics
6.5.5:22 The evaluation of an addition expression proceeds as follows:
6.5.5:23 The left operand is evaluated.
6.5.5:24 The right operand is evaluated.
6.5.5:25 If the type of both operands is the same integer type or floating-point type, then the addition expression evaluates to the sum of the operands, following the rules of unsigned integer addition for unsigned integer types, two’s complement addition for signed integer types, or floating-point addition for floating-point types. If unsigned integer addition or two’s complement addition is performed, then the operation may result in an arithmetic overflow.
6.5.5:26 Otherwise,
core::ops::Add::add(left_operand, right_operand)
is invoked.
6.5.5:27 The evaluation of a division expression proceeds as follows:
6.5.5:28 The left operand is evaluated.
6.5.5:29 The right operand is evaluated.
6.5.5:30 If the type of both operands is the same integer type or floating-point type, then the division expression evaluates to the quotient of the operands, following the rules of unsigned integer division for unsigned integer types, two’s complement division for signed integer types, or floating-point division for floating-point types.
6.5.5:31 If unsigned integer division is performed and the right operand is 0, then the operation results in a panic.
6.5.5:32 If two’s complement division is performed and the right operand is 0 or the result does not fit in the target type, then the operation results in a panic.
6.5.5:33 Otherwise,
core::ops::Div::div(left_operand, right_operand)
is invoked.
6.5.5:34 The evaluation of a multiplication expression proceeds as follows:
6.5.5:35 The left operand is evaluated.
6.5.5:36 The right operand is evaluated.
6.5.5:37 If the type of both operands is the same integer type or floating-point type, then the multiplication expression evaluates to the product of the operands, following the rules of unsigned integer multiplication for unsigned integer types, two’s complement multiplication for signed integer types, or floating-point multiplication for floating-point types. If unsigned integer multiplication or two’s complement multiplication is performed, then the operation may result in an arithmetic overflow.
6.5.5:38 Otherwise,
core::ops::Mul::mul(left_operand, right_operand)
is invoked.
6.5.5:39 The evaluation of a remainder expression proceeds as follows:
6.5.5:40 The left operand is evaluated.
6.5.5:41 The right operand is evaluated.
6.5.5:42 If the type of both operands is the same integer type or floating-point type, then the remainder expression evaluates to the remainder of the division of the left operand by the right operand, following the rules of unsigned integer division for unsigned integer types, two’s complement division for signed integer types, or floating-point division for floating-point types.
6.5.5:43 If unsigned integer division is performed and the right operand is 0, then the operation results in a panic.
6.5.5:44 If two’s complement division is performed and the right operand is 0 or the resulting remainder does not fit in the target type, then the operation results in a panic.
6.5.5:45 Otherwise,
core::ops::Rem::rem(left_operand, right_operand)
is invoked.
6.5.5:46 The evaluation of a subtraction expression proceeds as follows:
6.5.5:47 The left operand is evaluated.
6.5.5:48 The right operand is evaluated.
6.5.5:49 If the type of both operands is the same integer type or floating-point type, then the subtraction expression evaluates to the difference of the operands, following the rules of unsigned integer subtraction for unsigned integer types, two’s complement subtraction for signed integer types, or floating-point subtraction for floating-point types. If unsigned integer subtraction or two’s complement subtraction is performed, then the operation may result in an arithmetic overflow.
6.5.5:50 Otherwise,
core::ops::Sub::sub(left_operand, right_operand)
is invoked.
Examples
1 + 2
4.0 / 3.29
8.4 * 5.3
10 % 4
3 - 2
6.5.6. Bit Expressions¶
Syntax
BitExpression
::=BitAndExpression
|BitOrExpression
|BitXOrExpression
|ShiftLeftExpression
|ShiftRightExpression
BitAndExpression
::=LeftOperand
&RightOperand
BitOrExpression
::=LeftOperand
|RightOperand
BitXorExpression
::=LeftOperand
^RightOperand
ShiftLeftExpression
::=LeftOperand
<<RightOperand
ShiftRightExpression
::=LeftOperand
>>RightOperand
Legality Rules
6.5.6:1 A bit expression is an expression that computes a value from two operands using bit arithmetic.
6.5.6:2 A bit and expression is a bit expression that uses bit and arithmetic.
6.5.6:3
The type of the left operand of a bit and expression shall
implement the core::ops::BitAnd
trait where the type of the
right operand is the trait implementation type parameter.
6.5.6:4
The type of a bit and expression is associated type
core::ops::BitAnd::Output
.
6.5.6:5
The value of a bit and expression is the result of
core::ops::BitAnd::bitand(left_operand, right_operand)
.
6.5.6:6 A bit or expression is a bit expression that uses bit or arithmetic.
6.5.6:7
The type of the left operand of a bit or expression shall
implement the core::ops::BitOr
trait where the type of the
right operand is the trait implementation type parameter.
6.5.6:8
The type of a bit or expression is associated type
core::ops::BitOr::Output
.
6.5.6:9
The value of a bit or expression is the result of
core::ops::BitOr::bitor(left_operand, right_operand)
.
6.5.6:10 A bit xor expression is a bit expression that uses bit exclusive or arithmetic.
6.5.6:11
The type of the left operand of a bit xor expression shall
implement the core::ops::BitXor
trait where the type of the
right operand is the trait implementation type parameter.
6.5.6:12
The type of a bit xor expression is associated type
core::ops::BitXor::Output
.
6.5.6:13
The value of a bit xor expression is the result of
core::ops::BitXor::bitxor(left_operand, right_operand)
.
6.5.6:14 A shift left expression is a bit expression that uses bit shift left arithmetic.
6.5.6:15
The type of the left operand of a shift left expression shall
implement the core::ops::Shl
trait where the type of the
right operand is the trait implementation type parameter.
6.5.6:16
The type of a shift left expression is associated type
core::ops::Shl::Output
.
6.5.6:17
The value of a shift left expression is the result of
core::ops::Shl::shl(left_operand, right_operand)
.
6.5.6:18 A shift right expression is a bit expression that uses bit shift right arithmetic.
6.5.6:19
The type of the left operand of a shift right expression shall
implement the core::ops::Shr
trait where the type of the
right operand is the trait implementation type parameter.
6.5.6:20
The type of a shift right expression is associated type
core::ops::Shr::Output
.
6.5.6:21
The value of a shift right expression is the result of
core::ops::Shr::shr(left_operand, right_operand)
.
Dynamic Semantics
6.5.6:22 The evaluation of a bit and expression proceeds as follows:
6.5.6:23 The left operand is evaluated.
6.5.6:24 The right operand is evaluated.
6.5.6:25
core::ops::BitAnd::bitand(left_operand, right_operand)
is invoked.
6.5.6:26 The evaluation of a bit or expression proceeds as follows:
6.5.6:27 The left operand is evaluated.
6.5.6:28 The right operand is evaluated.
6.5.6:29
core::ops::BitOr::bitor(left_operand, right_operand)
is invoked.
6.5.6:30 The evaluation of a bit xor expression proceeds as follows:
6.5.6:31 The left operand is evaluated.
6.5.6:32 The right operand is evaluated.
6.5.6:33
core::ops::BitXor::bitxor(left_operand, right_operand)
is invoked.
6.5.6:34 The evaluation of a shift left expression proceeds as follows:
6.5.6:35 The left operand is evaluated.
6.5.6:36 The right operand is evaluated.
6.5.6:37 If the types of both operands are integer types, then the shift left expression evaluates to the value of the left operand whose bits are shifted left by the number of positions the right operand evaluates to. Vacated bits are filled with zeros.
lhs << rhs
evaluates to \(\mathrm{lhs} \times 2 ^ \mathrm{rhs}\), casted to the type of the left operand. If the value of the right operand is negative or greater than or equal to the width of the left operand, then the operation results in an arithmetic overflow.6.5.6:38 Otherwise,
core::ops::Shl::shl(left_operand, right_operand)
is invoked.
6.5.6:39 The evaluation of a shift right expression proceeds as follows:
6.5.6:40 The left operand is evaluated.
6.5.6:41 The right operand is evaluated.
6.5.6:42 If the types of both operands are integer types, then the shift right expression evaluates to the value of the left operand whose bits are shifted right by the number of positions the right operand evaluates to. If the type of the left operand is any signed integer type and is negative, then vacated bits are filled with ones. Otherwise, vacated bits are filled with zeros.
lhs >> rhs
evaluates to \(\mathrm{lhs} / 2^ \mathrm{rhs}\), casted to the type of the left operand. If the value of the right operand is negative, greater than or equal to the width of the left operand, then the operation results in an arithmetic overflow.6.5.6:43 Otherwise,
core::ops::Shr::shr(left_operand, right_operand)
is invoked.
Examples
0b1010 & 0b1100
0b1010 | 0b0011
0b1010 ^ 0b1001
13 << 3
-10 >> 2
6.5.7. Comparison Expressions¶
Syntax
ComparisonExpression
::=EqualsExpression
|GreaterThanExpression
|GreaterThanOrEqualsExpression
|LessThanExpression
|LessThanOrEqualsExpression
|NotEqualsExpression
EqualsExpression
::=LeftOperand
==RightOperand
GreaterThanExpression
::=LeftOperand
>RightOperand
GreaterThanOrEqualsExpression
::=LeftOperand
>=RightOperand
LessThanExpression
::=LeftOperand
<RightOperand
LessThanOrEqualsExpression
::=LeftOperand
<=RightOperand
NotEqualsExpression
::=LeftOperand
!=RightOperand
Legality Rules
6.5.7:1 A comparison expression is an expression that compares the values of two operands.
6.5.7:2 A comparison expression implicitly takes shared borrows of its operands.
6.5.7:3
The type of a comparison expression is type bool
.
6.5.7:4 An equals expression is a comparison expression that tests equality.
6.5.7:5
The type of the left operand of an equals expression shall
implement the core::cmp::PartialEq
trait where the type of the
right operand is the trait implementation type parameter.
6.5.7:6
The value of an equals expression is the result of
core::cmp::PartialEq::eq(&left_operand, &right_operand)
.
6.5.7:7 A greater-than expression is a comparison expression that tests for a greater-than relationship.
6.5.7:8
The type of the left operand of a greater-than expression shall
implement the core::cmp::PartialOrd
trait where the type of the
right operand is the trait implementation type parameter.
6.5.7:9
The value of a greater-than expression is the result of
core::cmp::PartialOrd::gt(&left_operand, &right_operand)
.
6.5.7:10 A greater-than-or-equals expression is a comparison expression that tests for a greater-than-or-equals relationship.
6.5.7:11
The type of the left operand of a
greater-than-or-equals expression shall implement the
core::cmp::PartialOrd
trait where the type of the
right operand is the trait implementation type parameter.
6.5.7:12
The value of a greater-than-or-equals expression is the result of
core::cmp::PartialOrd::ge(&left_operand, &right_operand)
.
6.5.7:13 A less-than expression is a comparison expression that tests for a less-than relationship.
6.5.7:14
The type of the left operand of a less-than expression shall
implement the core::cmp::PartialOrd
trait where the type of
the right operand is the trait implementation type parameter.
6.5.7:15
The value of a less-than expression is the result of
core::cmp::PartialOrd::lt(&left_operand, &right_operand)
.
6.5.7:16 A less-than-or-equals expression is a comparison expression that tests for a less-than-or-equals relationship.
6.5.7:17
The type of the left operand of a less-than-or-equals expression
shall implement the core::cmp::PartialOrd
trait where the type
of the right operand is the trait implementation type parameter.
6.5.7:18
The value of a less-than-or-equals expression is the result of
core::cmp::PartialOrd::le(&left_operand, &right_operand)
.
6.5.7:19 A not-equals expression is a comparison expression that tests for inequality.
6.5.7:20
The type of the left operand of a not-equals expression shall
implement the core::cmp::PartialEq
trait where the type of the
right operand is the trait implementation type parameter.
6.5.7:21
The value of a not-equals expression is the result of
core::cmp::PartialEq::ne(&left_operand, &right_operand)
.
Dynamic Semantics
6.5.7:22 The evaluation of an equals expression proceeds as follows:
6.5.7:23 The left operand is evaluated.
6.5.7:24 The right operand is evaluated.
6.5.7:25
core::cmp::PartialEq::eq(&left_operand, &right_operand)
is invoked.
6.5.7:26 The evaluation of a greater-than expression proceeds as follows:
6.5.7:27 The left operand is evaluated.
6.5.7:28 The right operand is evaluated.
6.5.7:29
core::cmp::PartialOrd::gt(&left_operand, &right_operand)
is invoked.
6.5.7:30 The evaluation of a greater-than-or-equals expression proceeds as follows:
6.5.7:31 The left operand is evaluated.
6.5.7:32 The right operand is evaluated.
6.5.7:33
core::cmp::PartialOrd::ge(&left_operand, &right_operand)
is invoked.
6.5.7:34 The evaluation of a less-than expression proceeds as follows:
6.5.7:35 The left operand is evaluated.
6.5.7:36 The right operand is evaluated.
6.5.7:37
core::cmp::PartialOrd::lt(&left_operand, &right_operand)
is invoked.
6.5.7:38 The evaluation of a less-than-or-equals expression proceeds as follows:
6.5.7:39 The left operand is evaluated.
6.5.7:40 The right operand is evaluated.
6.5.7:41
core::cmp::PartialOrd::le(&left_operand, &right_operand)
is invoked.
6.5.7:42 The evaluation of a not-equals expression proceeds as follows:
6.5.7:43 The left operand is evaluated.
6.5.7:44 The right operand is evaluated.
6.5.7:45
core::cmp::PartialEq::ne(&left_operand, &right_operand)
is invoked.
Examples
12 == 12
42 > 12
42 >= 35
42 < 109
42 <= 42
12 != 42
6.5.8. Lazy Boolean Expressions¶
Syntax
LazyBooleanExpression
::=LazyAndExpression
|LazyOrExpression
LazyAndExpression
::=LeftOperand
&&RightOperand
LazyOrExpression
::=LeftOperand
||RightOperand
Legality Rules
6.5.8:1 A lazy boolean expression is an expression that performs short circuit Boolean arithmetic.
6.5.8:2 A lazy and expression is a lazy boolean expression that uses short circuit and arithmetic.
6.5.8:3 A lazy or expression is a lazy boolean expression that uses short circuit or arithmetic.
6.5.8:4
The types of the operands of a lazy boolean expression shall
be type bool
.
6.5.8:5
The type of a lazy boolean expression is type bool
.
6.5.8:6
The value of a lazy boolean expression is either true
or
false
.
Dynamic Semantics
6.5.8:7 The evaluation of a lazy and expression proceeds as follows:
6.5.8:8 The left operand is evaluated.
6.5.8:9 If the left operand evaluated to
true
, then the right operand is evaluated and returned as the lazy and expression's value.6.5.8:10 Otherwise the lazy and expression evaluates to
false
.
6.5.8:11 The evaluation of a lazy or expression proceeds as follows:
6.5.8:12 The left operand is evaluated.
6.5.8:13 If the left operand evaluated to
false
, then the right operand is evaluated and returned as the lazy or expression's value.6.5.8:14 Otherwise the lazy or expression evaluates to
true
.
Examples
false && panic!()
this || that
6.5.9. Type Cast Expressions¶
Syntax
TypeCastExpression
::=Operand
asTypeSpecificationWithoutBounds
Legality Rules
6.5.9:1 A type cast expression is an expression that changes the type of an operand.
6.5.9:2 Cast or casting is the process of changing the type of an expression.
6.5.9:3
The TypeSpecificationWithoutBounds
describes the target type of the
type cast expression.
6.5.9:4 A type cast expression with the following characteristics performs a specialized cast:
6.5.9:5 An operand of a numeric type and a target numeric type perform a numeric cast.
6.5.9:6 An operand of an enum type and a target integer type perform enum cast. An enum cast converts the operand to its discriminant, followed by a numeric cast.
6.5.9:7 An operand of type
bool
or typechar
and a target integer type perform primitive-to-integer cast. A primitive-to-integer cast6.5.9:11 An operand of type
u8
and a target typechar
performs u8-to-char cast. A u8-to-char cast converts an operand of typeu8
to the value of the corresponding code point.6.5.9:12 An operand of type
*const T
or*mut T
and a target type*const V
or*mut V
whereV
implements thecore::marker::Sized
trait performs pointer-to-pointer cast.6.5.9:13 An operand of type
*const T
or*mut T
whereT
implements thecore::marker::Sized
trait and a target integer type perform pointer-to-address cast. A pointer-to-address cast produces an integer that represents the machine address of the referenced memory. If the integer type is smaller than the type of the operand, the address is truncated.6.5.9:14 An operand of integer type and target type
*const V
or*mut V
whereV
implements thecore::marker::Sized
trait perform address-to-pointer cast. An address-to-pointer cast produces a pointer that interprets the integer as a machine address.6.5.9:15 An operand of type
&mut [T; N]
and a target type*const T
perform array-to-pointer cast.6.5.9:16 An operand of a function item type and a target type
*const V
or*mut V
whereV
implements thecore::marker::Sized
trait perform function-item-to-pointer cast.6.5.9:17 An operand of a function item type and a target integer type perform function-to-address cast.
6.5.9:18 An operand of a function pointer type and a target type
*const V
or*mut V
whereV
implements thecore::marker::Sized
trait perform function-pointer-to-pointer cast.6.5.9:19 An operand of a function pointer type and a target integer type perform function-pointer-to-address cast. A function-pointer-to-address cast produces an integer that represents the machine address of the referenced function. If the integer type is smaller than the size of the function pointer type, the address is truncated.
6.5.9:20 A cast is legal when it either performs type coercion or is a specialized cast.
6.5.9:21 The type of a type cast expression is the target type.
6.5.9:22 The value of a type cast expression is the value of the operand after the cast.
Dynamic Semantics
6.5.9:23 The evaluation of a type cast expression evaluates its operand.
6.5.9:24 The evaluation of a numeric cast proceeds as follows:
6.5.9:25 Casting an operand of an integer type to a target integer type of the same size has no effect.
6.5.9:26 Casting an operand of an integer type to a target integer type with smaller size truncates the value of the operand.
6.5.9:27 Casting an operand of an integer type to a target integer type with a larger size either
6.5.9:30 Casting an operand of a floating-point type to a target integer type rounds the value of the operand towards zero. In addition, the type cast expression
6.5.9:31 Returns zero if the operand denotes
f32::NaN
orf64::NaN
respectively.6.5.9:32 Saturates the value of the operand to the maximum value of the target integer type if the operand's value exceeds the maximum value of the target integer type or denotes
f32::INFINITY
orf64::INFINITY
respectively.6.5.9:33 Saturates the value of the operand to the minimum value of the target integer type if the operand's value exceeds the minimum value of the target integer type or denotes
f32::NEG_INFINITY
orf64::NEG_INFINITY
respectively.
6.5.9:34 Casting an operand of an integer type to a target floating-point type produces the closest possible floating-point value. In addition, the type cast expression
6.5.9:35 Rounds the value of the operand preferring the value with an even least significant digit if exactly halfway between two floating-point numbers.
6.5.9:36 Produces
f32::INFINITY
orf64::INFINITY
of the same sign as the value of the operand when the value of the operand causes arithmetic overflow.
6.5.9:37 Casting an operand of type
f32
to a target typef64
is perfect and lossless.6.5.9:38 Casting an operand of type
f64
to target typef32
produces the closest possiblef32
value. In addition, the type cast expression6.5.9:39 Prefers the nearest value with an even least significant digit if exactly halfway between two floating-point numbers.
6.5.9:40 Produces
f32::INFINITY
of the same sign as the value of the operand when the value of the operand causes arithmetic overflow.
Examples
6.5.9:41
See 6.5.1:10 for the declaration of answer
.
answer as f64
6.5.10. Assignment Expressions¶
Syntax
AssignmentExpression
::=AssigneeOperand
=ValueOperand
AssigneeOperand
::=Operand
ValueOperand
::=Operand
Legality Rules
6.5.10:1 An assignment expression is an expression that assigns the value of a value operand to an assignee operand.
6.5.10:2 An assignee operand is the target operand of an assignment expression.
6.5.10:3 A value operand is an operand that supplies the value that is assigned to an assignee operand by an assignment expression.
6.5.10:4 The type of an assignment expression is the unit type.
6.5.10:5 The value of an assignment expression is the unit value.
6.5.10.1. Basic Assignment¶
Legality Rules
6.5.10.1:1 A basic assignment is an assignment expression that is not a destructuring assignment.
Dynamic Semantics
6.5.10.1:2 The evaluation of a basic assignment proceeds as follows:
6.5.10.1:3 The value operand is evaluated.
6.5.10.1:4 The assignee operand is evaluated.
6.5.10.1:5 The value denoted by the assignee operand is dropped, unless the assignee operand denotes an uninitialized variable or an uninitialized field of a variable.
6.5.10.1:6 The value of the value operand is passed into the place of the assignee operand.
Examples
this = 42
6.5.10.2. Destructuring Assignment¶
Legality Rules
6.5.10.2:1 A destructuring assignment is an assignment expression where the assignee operand is either an array expression, a struct expression, a tuple expression or a tuple struct call expression.
6.5.10.2:2 The assignee operand of a destructuring assignment is treated as an assignee pattern depending on its kind, as follows:
6.5.10.2:3 An array expression corresponds to a slice pattern with all the subexpressions lowered to their corresponding patterns.
6.5.10.2:4 A full range expression corresponds to a rest pattern if inside an array expression, otherwise this is a static error.
6.5.10.2:5 A place expression corresponds to an identifier pattern with a unique identifier and without keyword
ref
, keywordmut
, or a bound pattern.6.5.10.2:6 A struct expression corresponds to a struct pattern with all the subexpressions lowered to their corresponding patterns.
6.5.10.2:7 A tuple expression corresponds to a tuple pattern with all the subexpressions lowered to their corresponding patterns.
6.5.10.2:8 A tuple struct call expression corresponds to a tuple struct pattern with all the subexpressions lowered to their corresponding patterns.
6.5.10.2:9 An underscore expression corresponds to an underscore pattern.
6.5.10.2:10 The pattern that corresponds to a destructuring assignment shall be an irrefutable pattern.
6.5.10.2:11 A destructuring assignment is equivalent to a block expression of the following form:
6.5.10.2:12 The first statement is a let statement with its pattern equivalent to the lowered assignee pattern and its initialization expression equivalent to the value operand.
6.5.10.2:13 Then each bound identifier of the assignee pattern is an assignment expression used as a statement, as follows:
6.5.10.2:14 The bound identifier becomes the value operand of the new assignment expression, and
6.5.10.2:15 The corresponding expression from the assignee operand of the destructuring assignment becomes the assignee operand of the new assignment expression.
Dynamic Semantics
6.5.10.2:16 The evaluation of a destructuring assignment proceeds as follows:
6.5.10.2:17 The value operand is evaluated.
6.5.10.2:18 The assignee operand is evaluated by evaluating its operands in a left-to-right order.
6.5.10.2:19 Each value denoted by the assignee operand is dropped in left-to-right order, unless the assignee operand denotes an uninitialized variable or an uninitialized field of a variable.
6.5.10.2:20 The value of the value operand is passed into the place of the assignee operand.
Examples
(four, two) = (4, 2)
6.5.11. Compound Assignment Expressions¶
Syntax
CompoundAssignmentExpression
::=AdditionAssignmentExpression
|BitAndAssignmentExpression
|BitOrAssignmentExpression
|BitXorAssignmentExpression
|DivisionAssignmentExpression
|MultiplicationAssignmentExpression
|RemainderAssignmentExpression
|ShiftLeftAssignmentExpression
|ShiftRightAssignmentExpression
|SubtractionAssignmentExpression
AdditionAssignmentExpression
::=AssignedOperand
+=ModifyingOperand
BitAndAssignmentExpression
::=AssignedOperand
&=ModifyingOperand
BitOrAssignmentExpression
::=AssignedOperand
|=ModifyingOperand
BitXorAssignmentExpression
::=AssignedOperand
^=ModifyingOperand
DivisionAssignmentExpression
::=AssignedOperand
/=ModifyingOperand
MultiplicationAssignmentExpression
::=AssignedOperand
*=ModifyingOperand
RemainderAssignmentExpression
::=AssignedOperand
%=ModifyingOperand
ShiftLeftAssignmentExpression
::=AssignedOperand
<<=ModifyingOperand
ShiftRightAssignmentExpression
::=AssignedOperand
>>=ModifyingOperand
SubtractionAssignmentExpression
::=AssignedOperand
-=ModifyingOperand
AssignedOperand
::=Operand
ModifyingOperand
::=Operand
Legality Rules
6.5.11:1 A compound assignment expression is an expression that first computes a value from two operands and then assigns the value to an assigned operand.
6.5.11:2 A bit and assignment expression is a compound assignment expression that uses bit and arithmetic.
6.5.11:3 A bit or assignment expression is a compound assignment expression that uses bit or arithmetic.
6.5.11:4 A bit xor assignment expression is a compound assignment expression that uses bit exclusive or arithmetic.
6.5.11:5 A division assignment expression is a compound assignment expression that uses division.
6.5.11:6 A multiplication assignment expression is a compound assignment expression that uses multiplication.
6.5.11:7 A remainder assignment expression is a compound assignment expression that uses remainder division.
6.5.11:8 A shift left assignment expression is a compound assignment expression that uses bit shift left arithmetic.
6.5.11:9 A shift right assignment expression is a compound assignment expression that uses bit shift right arithmetic.
6.5.11:10 A subtraction assignment expression is a compound assignment expression that uses subtraction.
6.5.11:11 An assigned operand is the target operand of a compound assignment expression.
6.5.11:12 A modifying operand is an operand that supplies the value that is used in the calculation of a compound assignment expression.
6.5.11:13 An assigned operand shall denote a mutable assignee expression.
6.5.11:14 The type of a compound assignment is the unit type.
6.5.11:15 The value of a compound assignment is the unit value.
6.5.11:16
The type of the assigned operand of an addition assignment shall
implement the core::ops::AddAssign
trait where the type of the right
operand is the trait implementation type parameter.
6.5.11:17
The type of the assigned operand of a bit and assignment shall
implement the core::ops::BitAndAssign
trait where the type of
the modifying operand is the trait implementation type parameter.
6.5.11:18
The type of the assigned operand of a bit or assignment shall
implement the core::ops::BitOrAssign
trait where the type of
the modifying operand is the trait implementation type parameter.
6.5.11:19
The type of the assigned operand of a bit xor assignment shall
implement the core::ops::BitXorAssign
trait where the type of
the modifying operand is the trait implementation type parameter.
6.5.11:20
The type of the assigned operand of a division assignment shall
implement the core::ops::DivAssign
trait where the type of the
modifying operand is the trait implementation type parameter.
6.5.11:21
The type of the assigned operand of a multiplication assignment
shall implement the core::ops::MulAssign
trait where the type
of the modifying operand is the trait implementation
type parameter.
6.5.11:22
The type of the assigned operand of a remainder assignment shall
implement the core::ops::RemAssign
trait where the type of the
modifying operand is the trait implementation type parameter.
6.5.11:23
The type of the assigned operand of a shift left assignment shall
implement the core::ops::ShlAssign
trait where the type of the
modifying operand is the trait implementation type parameter.
6.5.11:24
The type of the assigned operand of a shift right assignment
shall implement the core::ops::ShrAssign
trait where the type
of the modifying operand is the trait implementation
type parameter.
6.5.11:25
The type of the assigned operand of a subtraction assignment
shall implement the core::ops::SubAssign
trait where the type
of the modifying operand is the trait implementation
type parameter.
Dynamic Semantics
6.5.11:26 The evaluation of a compound assignment proceeds as follows:
6.5.11:27 If the types of both operands are integer types or floating-point types, then
6.5.11:28 The modifying operand is evaluated.
6.5.11:29 The assigned operand is evaluated.
6.5.11:30 The appropriate function is invoked as indicated below.
6.5.11:31 Otherwise
6.5.11:32 The assigned operand is evaluated.
6.5.11:33 The modifying operand is evaluated.
6.5.11:34 The appropriate function is invoked as indicated below.
6.5.11:35
For an addition assignment,
core::ops::AddAssign::add_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:36
For a bit and assignment,
core::ops::BitAndAssign::bitand_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:37
For a bit or assignment,
core::ops::BitOrAssign::bitor_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:38
For a bit xor assignment,
core::ops::BitXorAssign::bitxor_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:39
For a division assignment,
core::ops::DivAssign::div_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:40
For a multiplication assignment,
core::ops::MulAssign::mul_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:41
For a remainder assignment,
core::ops::RemAssign::rem_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:42
For a shift left assignment,
core::ops::ShlAssign::shl_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:43
For a shift right assignment,
core::ops::ShrAssign::shr_assign(&mut assigned_operand, modifying_operand)
is invoked.
6.5.11:44
For a subtraction assignment,
core::ops::SubAssign::sub_assign(&mut assigned_operand, modifying_operand)
is invoked.
Examples
let mut result = 42;
result += 1
result &= 59
result /= 3
result ^= 2
result *= 81
result |= 9402
result %= 7
result <<= 2
result >>= 3
result -= 0
6.6. Underscore Expressions¶
Syntax
UnderscoreExpression
::=
_
Legality Rules
6.6:1 An underscore expression is an expression that acts as a placeholder in a destructuring assignment.
6.6:2 An underscore expression shall appear in the assigned operand of a destructuring assignment.
Examples
let pair = (1, 2);
let mut second = 0;
(_, second) = pair;
6.7. Parenthesized Expressions¶
Syntax
ParenthesizedExpression
::= (Operand
)
Legality Rules
6.7:1 A parenthesized expression is an expression that groups other expressions.
6.7:2 The type of a parenthesized expression is the type of its operand.
6.7:3 The value of a parenthesized expression is the value of its operand.
Dynamic Semantics
6.7:4 The evaluation of a parenthesized expression evaluates its operand.
Examples
(1 + 2) * 3
6.8. Array Expressions¶
Syntax
ArrayExpression
::= [ArrayElementExpression
? ]ArrayElementExpression
::=ArrayElementConstructor
|ArrayRepetitionConstructor
ArrayElementConstructor
::=ExpressionList
ArrayRepetitionConstructor
::=RepeatOperand
;SizeOperand
RepeatOperand
::=Operand
SizeOperand
::=Operand
Legality Rules
6.8:1 An array expression is an expression that constructs an array.
6.8:2 An array element constructor is an array expression that lists all elements of the array being constructed.
6.8:3 An array repetition constructor is an array expression that specifies how many times an element is repeated in the array being constructed.
6.8:4 A repeat operand is an operand that specifies the element being repeated in an array repetition constructor.
6.8:5 A size operand is an operand that specifies the size of an array or an array type.
6.8:6 The size operand shall be a constant expression.
6.8:7 The types of the operands of an array element constructor shall be unifiable.
6.8:8
If the size operand is greater than one, then the type of the
repeat operand shall implement the core::copy::Copy
trait
or the repeat operand shall be a path expression resolving to a
constant.
6.8:9
The type of the size operand shall be type usize
.
6.8:10
The type of an array expression is [T; N]
, where T
is the
element type and N
is the size of the array. The size of an
array is determined as follows:
6.8:11 If the array expression appears with an array element constructor, then the size is the number of operands in the array element constructor.
6.8:12 Otherwise the size is the value of size operand.
6.8:13 The value of an array expression is the constructed array.
Dynamic Semantics
6.8:14 The evaluation of an array expression with an array element constructor evaluates its operands in left-to-right order.
6.8:15 The evaluation of an array expression with an array repetition constructor proceeds as follows:
6.8:16 If the value of the size operand is greater than zero, then:
6.8:17 If the repeat operand denotes a constant, the repeat operand is evaluated once and its value is passed by copy size operand's value times.
6.8:18 Otherwise the repeat operand is evaluated size operand's value times.
6.8:19 Otherwise the repeat operand is evaluated once.
Examples
[1, 2, 3]
["one", "two", "three",]
6.8:20 Two dimensional array.
[[0, 0], [0, 1], [1, 0], [1, 1]]
6.8:21 An array of nine 42s.
[42; 9]
6.9. Indexing Expressions¶
Syntax
IndexExpression
::=IndexedOperand
[IndexingOperand
]IndexedOperand
::=Operand
IndexingOperand
::=Operand
Legality Rules
6.9:1
An indexable type is a type that implements the
core::ops::Index
trait.
6.9:2 An index expression is an expression that indexes into a value of an indexable type.
6.9:3 An indexed operand is an operand which indicates the value being indexed into by an index expression.
6.9:4 An indexing operand is an operand which specifies the index of an index expression.
6.9:5 An index expression is a constant expression if the indexing operand and indexed operand are constant expressions.
6.9:6
The type of the indexing operand is the generic parameter of the
core::ops::Index
implementation of the type of the
indexed operand.
6.9:7 If the indexed operand is evaluated in a value expression context, then
6.9:8 The type of the indexed operand shall implement the
core::ops::Index
trait.6.9:9 The type of the index expression is
&T
, whereT
is associated typecore::ops::Index::Output
.
6.9:10 If the indexed operand is mutable and the index expression is evaluated in a mutable place expression context, then
6.9:11 The type of the indexed operand shall implement the
core::ops::IndexMut
trait.6.9:12 The type of the index expression is
&mut T
, whereT
is the element type of the indexed operand‘s type.
6.9:13 The value of an index expression is the indexed memory location.
Dynamic Semantics
6.9:14 The evaluation of an index expression proceeds as follows:
6.9:15 The indexed operand is evaluated.
6.9:16 The indexing operand is evaluated.
6.9:17 If the index expression is evaluated in a mutable place expression context, then expression
*core::ops::IndexMut::index_mut(&mut indexed_operand, indexing_operand)
is evaluated.6.9:18 Otherwise expression
*core::ops::Index::index(&indexed_operand, indexing_operand)
is evaluated.
Examples
let a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
a[1][2]
6.9:19 Evaluates to 6.
6.10. Tuple Expressions¶
Syntax
TupleExpression
::= (TupleInitializerList
? )TupleInitializerList
::=ExpressionList
Legality Rules
6.10:1 A tuple expression is an expression that constructs a tuple.
6.10:2 A tuple initializer is an operand that provides the value of a tuple field in a tuple expression.
6.10:3
The type of a tuple expression is (T1, T2, ..., TN)
, where T1
is the type of the first tuple initializer, T2
is the type of
the second tuple initializer, and TN
is the type of the N
-th
tuple initializer.
6.10:4
The value of a tuple expression is (V1, V2, ..., VN)
, where V1
is the value of the first tuple initializer, V2
is the value
of the second tuple initializer, and VN
is the value of the
N
-th tuple initializer.
Dynamic Semantics
6.10:5 The evaluation of a tuple expression evaluates its tuple initializers in left-to-right order.
Examples
()
(1.2, 3.4)
("hello", 42i16, true)
6.11. Struct Expressions¶
Syntax
StructExpression
::=Constructee
{StructExpressionContent
? }Constructee
::=PathExpression
StructExpressionContent
::=BaseInitializer
|FieldInitializerList
(,BaseInitializer
| ,?)BaseInitializer
::= ..Operand
FieldInitializerList
::=FieldInitializer
(,FieldInitializer
)*FieldInitializer
::=IndexedInitializer
|NamedInitializer
|ShorthandInitializer
IndexedInitializer
::=FieldIndex
:Expression
NamedInitializer
::=Identifier
:Expression
ShorthandInitializer
::=Identifier
Legality Rules
6.11:1 A struct expression is an expression that constructs an enum value, a struct value, or a union value.
6.11:2 A constructee indicates the enum variant, struct, or union whose value is being constructed by a struct expression.
6.11:3 A base initializer is a construct that specifies an enum value, or a struct value to be used as a base for construction in a struct expression.
6.11:4 The type of a base initializer is the type of its operand. The type of a base initializer shall be the same as the type of the constructee.
6.11:5 An indexed initializer is a construct that specifies the index and initial value of a field in a struct expression.
6.11:6 An indexed initializer matches a field of the constructee when the field index of the indexed initializer resolves to a valid position of a field in the constructee. Such an indexed initializer is a matched indexed initializer.
6.11:7 The type of the operand of an indexed initializer and the type of the matched field shall be unifiable.
6.11:8 The value of an indexed initializer is the value of its operand.
6.11:9 A named initializer is a construct that specifies the name and initial value of a field in a struct expression.
6.11:10 A named initializer matches a field of the constructee when its identifier and the name of the field are the same. Such a named initializer is a matched named initializer.
6.11:11 The type of a named initializer and the type of the matched field shall be unifiable.
6.11:12 The value of a named initializer is the value of its expression.
6.11:13 A shorthand initializer is a construct that specifies the name of a field in a struct expression.
6.11:14 A shorthand initializer is equivalent to a named initializer where both the identifier and the expression of the named initializer denote the identifier of the shorthand initializer.
6.11:15 A shorthand initializer matches a field of the constructee when its identifier and the name of the field are the same. Such a shorthand initializer is a matched shorthand initializer.
6.11:16 The type of a shorthand initializer and the type of the matched field shall be unifiable.
6.11:17 The value of a shorthand initializer is the value its identifier resolves to.
6.11:18 The type of a struct expression is the type of the constructee.
6.11:19 The value of a struct expression is the enum value, struct value, or union value in construction.
6.11:20 If the constructee is a record enum variant or a record struct, then
6.11:21 For each field of the constructee, the struct expression shall either:
6.11:22 Contain at most one matched named initializer, or
6.11:23 Contain at most one matched shorthand initializer, or
6.11:24 Have exactly one base initializer.
6.11:25 A base initializer is allowed even if all fields of the constructee have been matched.
6.11:26 If the constructee is a tuple enum variant or a tuple struct, then
6.11:27 For each field of the constructee, the struct expression shall either:
6.11:28 Contain at most one matched indexed initializer, or
6.11:29 Have exactly one base initializer.
6.11:30 A base initializer is allowed even if all fields of the constructee have been matched.
6.11:31 If the constructee is a union type, then
6.11:32 The struct expression shall not contain a base initializer.
6.11:33 For the single field of the constructee, the struct expression shall either:
6.11:34 Contain exactly one matched named initializer, or
6.11:35 Contain exactly one matched shorthand initializer.
6.11:36 If the constructee is a unit enum variant or a unit struct, then the struct expression shall have at most one base initializer.
6.11:37 If a base initializer is supplied, then for each field that was not matched in the struct expression the value of the corresponding field of the base initializer is passed to the field of the constructee.
Dynamic Semantics
6.11:38 The evaluation of a struct expression evaluates its operands in a left-to-right order.
Examples
enum Occupation {
Engineer,
Gardener
}
struct Employee {
name: String,
age: u16,
occupation: Occupation
compensation: u32
}
let alice = Employee {
name: "Alice".to_string(),
age: 23,
occupation: Occupation::Engineer
compensation: 250_000
};
let age = 45;
let bob = Employee {
name: "Bob".to_string(), // matched named initializer
age, // matched shorthand initializer
.. alice // equivalent to alice.occupation, alice.compensation
};
union Union {
int: u32,
float: f32
}
let u1 = Union { int: 0 };
let u2 = Union { float: 0.0 };
6.12. Invocation Expressions¶
6.12.1. Call Expressions¶
Syntax
CallExpression
::=CallOperand
(ArgumentOperandList
? )CallOperand
::=Operand
ArgumentOperandList
::=ExpressionList
Legality Rules
6.12.1:1 A call expression is an expression that invokes a function or constructs a tuple enum variant value or a tuple struct value.
6.12.1:2 An argument operand is an operand which is used as an argument in a call expression or a method call expression.
6.12.1:3 A call operand is the function being invoked or the tuple enum variant value or the tuple struct value being constructed by a call expression.
6.12.1:4 A tuple struct call expression is a call expression where the call operand resolves to a tuple struct.
6.12.1:5
A callee type is either a function item type, a
function pointer type, a tuple enum variant, a
tuple struct type, or a type that implements any of the
core::ops::Fn
, core::ops::FnMut
, or core::ops::FnOnce
traits.
6.12.1:6
The type of a call expression is the return type of the invoked
function, the type of the tuple enum variant or the
tuple struct being constructed, or associated type
core::ops::FnOnce::Output
.
6.12.1:7 A call expression whose callee type is either an external function item type, an unsafe function item type, or an unsafe function pointer type shall require unsafe context.
6.12.1:8 The value of a call expression is determined as follows:
6.12.1:9 If the callee type is a function item type or a function pointer type, then the value is the result of invoking the corresponding function with the argument operands.
6.12.1:10 If the callee type is a tuple enum variant or a tuple struct type, then the value is the result of constructing the tuple enum variant or the tuple struct with the argument operands.
6.12.1:11 If the callee type implements the
core::ops::Fn
trait, then the value is the result of invokingcore::ops::Fn::call(adjusted_call_operand, argument_operand_tuple)
, whereadjusted_call_operand
is the adjusted call operand, andargument_operand_tuple
is a tuple that wraps the argument operands.6.12.1:12 If the call operand implements the
core::ops::FnMut
trait, then the value is the result of invokingcore::ops::FnMut::call_mut(adjusted_call_operand, argument_operand_tuple),
whereadjusted_call_operand
is the adjusted call operand, andargument_operand_tuple
is a tuple that wraps the argument operands.6.12.1:13 If the call operand implements the
core::ops::FnOnce
trait, then the value is the result of invokingcore::ops::FnOnce::call_once(adjusted_call_operand, argument_operand_tuple),
whereadjusted_call_operand
is the adjusted call operand, andargument_operand_tuple
is a tuple that wraps the argument operands.
6.12.1:14 A call expression is subject to call resolution.
Dynamic Semantics
6.12.1:15 The evaluation of a call expression proceeds as follows:
6.12.1:16 The call operand is evaluated.
6.12.1:17 The argument operands are evaluated in left-to-right order.
6.12.1:18 If the adjusted call operand is a function item type or function pointer type, then corresponding function is invoked.
6.12.1:19 If the type of the call operand implements the
core::ops::Fn
trait, thencore::ops::Fn::call(adjusted_call_operand, argument_operand_tuple)
is invoked.6.12.1:20 If the type of the call operand implements the
core::ops::FnMut
trait, thencore::ops::FnMut::call_mut(adjusted_call_operand, argument_operand_tuple)
is invoked.6.12.1:21 If the type of the call operand implements the
core::ops::FnOnce
trait, thencore::ops::FnOnce::call_once(adjusted_call_operand, argument_operand_tuple)
is invoked.
Undefined Behavior
6.12.1:22 It is undefined behavior to call a function with an ABI other than the ABI the function was defined with.
Examples
let three: i32 = add(1, 2);
6.12.2. Method Call Expressions¶
Syntax
MethodCallExpression
::=ReceiverOperand
.MethodOperand
(ArgumentOperandList
? )ReceiverOperand
::=Operand
MethodOperand
::=PathExpressionSegment
Legality Rules
6.12.2:1 A method call expression is an expression that invokes a method of a variable.
6.12.2:2 A receiver operand is an operand that denotes the value whose method is being invoked by a method call expression.
6.12.2:3 A method operand is an operand that denotes the method being invoked by a method call expression.
6.12.2:4 The type of a method call expression is the return type of the invoked method.
6.12.2:5 The value of a method call expression is the value returned by the invoked method.
6.12.2:6 A method call expression is subject to method resolution.
Dynamic Semantics
6.12.2:7 The evaluation of a method call expression proceeds as follows:
6.12.2:8 The receiver operand is evaluated.
6.12.2:9 The argument operands are evaluated in left-to-right order.
6.12.2:10 The method is invoked.
Examples
trait Command {
fn execute(&self);
}
struct ClickCommand { ... }
impl ClickCommand for Command {
fn execute(&self) {
println!("Someone clicked me!")
}
}
let click = ClickCommand { ... };
click.execute();
6.12.3. Call Conformance¶
6.12.3:1 A method call expression is equivalent to a call expression where the call operand is the resolved method and the adjusted receiver operand is prepended to the argument operands.
6.12.3:2 An argument operand matches a function parameter or field of the callee type when its position and the position of the function parameter or field are the same. Such an argument operand is a matched argument operand.
6.12.3:3 The type of a matched argument operand and the type of the corresponding function parameter or field shall be unifiable.
6.12.3:4 The number of argument operands shall be equal to the number of fields or function parameters of the callee type.
6.13. Field Access Expressions¶
Syntax
FieldAccessExpression
::=ContainerOperand
.FieldSelector
ContainerOperand
::=Operand
FieldSelector
::=IndexedFieldSelector
|NamedFieldSelector
IndexedFieldSelector
::=DecimalLiteral
NamedFieldSelector
::=Identifier
Legality Rules
6.13:1 A field access expression is an expression that accesses a field of a value.
6.13:2 A container operand is an operand that indicates the value whose field is selected in a field access expression.
6.13:3 A field selector is a construct that selects the field to be accessed in a field access expression.
6.13:4 A selected field is a field that is selected by a field access expression.
6.13:5 The type of a field access expression is the type of the selected field.
6.13:6 The value of a field access expression is the value of the selected field.
6.13:7 Reading the selected field of a union shall require unsafe context.
6.13:8
Writing to the selected field of a union where the type of the
selected field implements the core::marker::Copy
trait or the
core::mem::ManuallyDrop
trait shall not require unsafe context.
6.13:9
Writing to and then reading from the selected field of a union
subject to attribute repr
is equivalent to invoking function
core::mem::transmute<write_type, read_type>(field_bits)
where write_type
is the type used at the time of writing the selected field,
read_type
is the type used at the time of reading the
selected field, and field_bits
is the bit representation of the
selected field.
6.13:10 A field access expression is subject to field resolution.
Undefined Behavior
6.13:11 It is undefined behavior reading the selected field of a union type when it contains data that is invalid for the selected field‘s type.
Dynamic Semantics
6.13:12 The evaluation of a field access expression evaluates its container operand.
Examples
6.13:13
See 6.11:38 for the declaration of alice
.
alice.name
6.13:14
The following indexed field access evaluates to 42
.
("hello", 42i16, true).1
6.14. Closure Expressions¶
Syntax
ClosureExpression
::= move? |ClosureParameterList
? | (ClosureBody
|ClosureBodyWithReturnType
)ClosureBody
::=Expression
ClosureBodyWithReturnType
::=ReturnTypeWithoutBounds
BlockExpression
ReturnTypeWithoutBounds
::= ->TypeSpecificationWithoutBounds
ClosureParameterList
::=ClosureParameter
(,ClosureParameter
)* ,?ClosureParameter
::=OuterAttributeOrDoc
*PatternWithoutAlternation
TypeAscription
?
Legality Rules
6.14:1 A closure expression is an expression that defines a closure type and constructs a value of that type.
6.14:2 The return type of a closure type is determined as follows:
6.14:3 If the closure expression specifies a
ClosureBodyWithReturnType
, then the return type is the specifiedReturnTypeWithoutBounds
.6.14:4 Otherwise the return type is the type of the closure body.
6.14:5 A closure body is a construct that represents the executable portion of a closure expression.
6.14:6 A closure body denotes a new control flow boundary.
6.14:7 A closure body is subject to capturing.
6.14:8 A closure parameter is a construct that yields a set of bindings that bind matched input values to names at the site of a call expression or a method call expression.
6.14:9 The type of a closure parameter is determined as follows:
6.14:10 If the closure parameter lacks a
TypeSpecification
, the type is inferred form the usage of the closure parameter.
6.14:12 The pattern of a closure parameter shall be an irrefutable pattern.
6.14:13 The expected type of the pattern of a closure parameter is the type of the closure parameter.
6.14:14 The bindings of all patterns of all closure parameters of a closure expression shall not shadow another.
6.14:15 The type of a closure expression is the unique anonymous closure type defined by it.
6.14:16 The value of a closure expression is the value of the unique anonymous closure type instantiated with the selected capture targets.
Dynamic Semantics
6.14:17 The evaluation of a closure expression proceeds as follows:
6.14:18 An anonymous value of an unique anonymous closure type is created.
Examples
fn do_ten_times<F>(consumer: F) where F: Fn(i32) {
for times in 0 .. 10 {
consumer(times);
}
}
do_ten_times(|value: i32| { println!("value: {}", value)});
6.15. Loop Expressions¶
Syntax
LoopExpression
::=Label
?LoopContent
Label
::= 'NonKeywordIdentifier
:LoopContent
::=ForLoopExpression
|InfiniteLoopExpression
|WhileLetLoopExpression
|WhileLoopExpression
LoopBody
::=BlockExpression
Legality Rules
6.15:1 A loop expression is an expression that evaluates a block expression continuously as long as some criterion holds true.
6.15:2 A loop body is the block expression of a loop expression.
6.15:3 The type of the loop body shall be the unit type.
6.15:4 An anonymous loop expression is a loop expression without a label.
6.15:5 A named loop expression is a loop expression with a label.
Dynamic Semantics
6.15:6 A loop expression is terminated when its block expression is no longer evaluated.
6.15.1. For Loops¶
Syntax
ForLoopExpression
::= forPattern
inSubjectExpression
LoopBody
Legality Rules
6.15.1:1 A for loop expression is a loop expression that continues to evaluate its loop body as long as its subject expression yields a value.
6.15.1:2
The type of a subject expression shall implement the
core::iter::IntoIterator
trait.
6.15.1:3
The expected type of the pattern is the associated type core::iter::IntoIterator::Item
of the subject expression‘s core::iter::IntoIterator
implementation.
6.15.1:4 The type of a for loop expression is the unit type.
6.15.1:5 The value of a for loop expression is the unit value.
Dynamic Semantics
6.15.1:6 The evaluation of a for loop expression of the form
'label: for pattern in subject_expression {
/* loop body */
}
6.15.1:7 is equivalent to the evaluation of the following block expression:
{
let result =
match core::iter::IntoIterator::into_iter
(subject_expression)
{
mut iter => 'label: loop {
let mut next_value;
match core::iter::Iterator::next(&mut iter) {
Option::Some(value) => next_value = value,
Option::None => break
};
let pattern = next_value;
let () = { /* loop body */ };
}
};
result
}
Examples
let favorite_fruits = &["apples", "pears", "strawberries"];
for fruit in favorite_fruits {
println!("I like eating {}.", fruit);
}
6.15.2. Infinite Loops¶
Syntax
InfiniteLoopExpression
::= loopLoopBody
Legality Rules
6.15.2:1 An infinite loop expression is a loop expression that continues to evaluate its loop body indefinitely.
6.15.2:2 The type of an infinite loop expression is determined as follows:
6.15.2:3 If the infinite loop expression does not contain a break expression, then the type is the never type.
6.15.2:4 If the infinite loop expression contains at least one break expression, then the type is the unified type of the break types of all break expressions.
6.15.2:5 The value of an infinite loop expression is determined as follows:
6.15.2:6 If the infinite loop expression does not contain a break expression, then the value is the unit value.
6.15.2:7 If the infinite loop expression contains at least one break expression, then the value is the break value of the break expression that broke out of the loop expression.
Dynamic Semantics
6.15.2:8 The evaluation of an infinite loop expression proceeds as follows:
6.15.2:9 The block expression is evaluated.
6.15.2:10 Control restarts the evaluation of the infinite loop expression.
Examples
loop {
println!("I am alive!");
}
6.15.3. While Loops¶
Syntax
WhileLoopExpression
::= whileIterationExpression
LoopBody
IterationExpression
::=SubjectExpression
Legality Rules
6.15.3:1 A while loop expression is a loop expression that continues to evaluate its loop body as long as its iteration expression holds true.
6.15.3:2 An iteration expression is an expression that provides the criterion of a while loop expression.
6.15.3:3
The type of an iteration expression shall be type bool
.
6.15.3:4 The type of a while loop expression is the unit type.
6.15.3:5 The value of a while loop expression is the unit value.
Dynamic Semantics
6.15.3:6 The evaluation of a while loop expression proceeds as follows:
6.15.3:7 The iteration expression is evaluated.
6.15.3:8 If the iteration expression evaluated to
true
, then:6.15.3:9 The block expression is evaluated.
6.15.3:10 Control restarts the evaluation of the while loop expression.
Examples
let mut counter = 0;
while counter < 5 {
counter += 1;
println("iteration {}", counter);
}
6.15.4. While Let Loops¶
Syntax
WhileLetLoopExpression
::= while letPattern
=SubjectLetExpression
LoopBody
Legality Rules
6.15.4:1 A while let loop expression is a loop expression that continues to evaluate its loop body as long as its subject let expression yields a value that can be matched against its pattern.
6.15.4:2 The expected type of the pattern is the type of the subject let expression.
6.15.4:3 The type of a while let loop expression is the unit type.
6.15.4:4 The value of a while let loop expression is the unit value.
Dynamic Semantics
6.15.4:5 The evaluation of a while let loop expression of the form
'label: let pattern = subject_let_expression {
/* loop body */
}
6.15.4:6 shall be equivalent to the evaluation the following infinite loop:
'label: loop {
match subject_let_expression {
pattern => { /* loop body */ },
_ => break
}
}
Examples
let mut favorite_animals = vec!["cats", "dogs", "otters"];
while let Some(animal) = favorite_animals.pop() {
println!("I like petting {}", animal);
}
6.15.5. Loop Labels¶
Syntax
LabelIndication
::= 'NonKeywordIdentifier
Legality Rules
6.15.5:1 A label indication is a construct that indicates a label.
6.15.5:2 A label indication shall indicate a label of an enclosing named block expression or named loop expression that does not pass a control flow boundary in order to reach the enclosing named block expression or named loop expression.
6.15.6. Break Expressions¶
Syntax
BreakExpression
::= breakLabelIndication
?Operand
?
Legality Rules
6.15.6:1 A break expression is an expression that terminates a loop expression or a named block expression.
6.15.6:2 A break expression shall appear within a loop body or a named block expression.
6.15.6:3 If a break expression appears within a named block expression, then the break expression shall have a label indication.
6.15.6:4 The label indication of a break expression shall resolve to the label of an enclosing named block expression or named loop expression.
6.15.6:5 A break expression with a label indication is associated with the named block expression or named loop expression whose label is indicated by the label indication.
6.15.6:6 A break expression without a label indication is associated with the innermost enclosing loop expression.
6.15.6:7 If a break expression appears within a loop expression, then the break expression shall have an operand only when it is associated with an infinite loop.
6.15.6:8 The type of a break expression is the never type.
6.15.6:9 Break type is the type of the operand of a break expression.
6.15.6:10 The break type is determined as follows:
6.15.6:11 If the break expression lacks an operand, then the break type is the unit type.
6.15.6:12 If the break expression has an operand, then the break type is the type of its operand.
6.15.6:13 Break value is the value of the operand of a break expression.
6.15.6:14 The break value is determined as follows:
6.15.6:15 If the break expression lacks an operand, then the break value is the unit value.
6.15.6:16 If the break expression has an operand, then the break value is the value of its operand.
Dynamic Semantics
6.15.6:17 If a break expression appears within a loop expression, then the evaluation of the break expression proceeds as follows:
6.15.6:18 The operand is evaluated.
6.15.6:19 All enclosing loop expressions upto and including the associated loop expression are terminated.
6.15.6:20 If a break expression appears within a named block expression, then the evaluation of the break expression proceeds as follows:
6.15.6:21 The operand is evaluated.
6.15.6:22 All enclosing named block expressions upto and including the associated named block expression are terminated.
Examples
6.15.6:23 The following break expression terminates both the inner and the outer loop.
'outer: loop {
'inner: loop {
break 'outer;
}
}
6.15.7. Continue Expressions¶
Syntax
ContinueExpression
::= continueLabelIndication
?
Legality Rules
6.15.7:1 A continue expression shall appear within a loop expression.
6.15.7:2 A continue expression without a label indication is associated with the innermost enclosing loop expression.
6.15.7:3 A continue expression with a label indication is associated with a named loop expression whose label is indicated by the label indication.
6.15.7:4 The type of a continue expression is the never type.
Dynamic Semantics
6.15.7:5 The evaluation of a continue expression proceeds as follows:
6.15.7:6 If the continue expression appears with a label indication, then all enclosing loop expressions upto and including the associated loop expression are terminated.
6.15.7:7 The evaluation of the associated loop expression is restarted.
Examples
6.15.7:8
The following continue expression terminates and restarts game_loop
.
'game_loop: loop {
if is_paused() {
continue;
}
. . .
}
6.16. Range Expressions¶
Syntax
RangeExpression
::=RangeFromExpression
|RangeFromToExpression
|RangeFullExpression
|RangeInclusiveExpression
|RangeToExpression
|RangeToInclusiveExpression
RangeFromExpression
::=RangeExpressionLowBound
..RangeFromToExpression
::=RangeExpressionLowBound
..RangeExpressionHighBound
RangeFullExpression
::= ..RangeInclusiveExpression
::=RangeExpressionLowBound
..=RangeExpressionHighBound
RangeToExpression
::= ..RangeExpressionHighBound
RangeToInclusiveExpression
::= ..=RangeExpressionHighBound
RangeExpressionLowBound
::=Operand
RangeExpressionHighBound
::=Operand
Legality Rules
6.16:1 A range expression is an expression that constructs a range.
6.16:2 A range expression low bound is an operand that specifies the start of a range.
6.16:3 A range expression high bound is an operand that specifies the end of a range.
6.16:4 If a range expression has two operands, then the types of the operands shall be unifiable.
6.16:5 A range-from expression is a range expression that specifies an included range expression low bound.
6.16:6
The type of a range-from expression is core::ops::RangeFrom
.
6.16:7
The value of a range-from expression is
core::ops::RangeFrom { start: range_expression_low_bound }
.
6.16:8 A range-from-to expression is a range expression that specifies an included range expression low bound and an excluded range expression high bound.
6.16:9
The type of a range-from-to expression is core::ops::Range
.
6.16:10
The value of a range-from-to expression is
core::ops::Range { start: range_expression_low_bound, end: range_expression_high_bound }
.
6.16:11 A range-full expression is a range expression that covers the whole range of a type.
6.16:12
The type of a range-full expression is core::ops::RangeFull
.
6.16:13
The value of a range-full expression is core::ops::RangeFull {}
.
6.16:14 A range-inclusive expression is a range expression that specifies an included range expression low bound and an included range expression high bound.
6.16:15
The type of a range-inclusive expression is
core::ops::RangeInclusive
.
6.16:16
The value of a range-inclusive expression is
core::ops::RangeInclusive::new(range_expression_low_bound, range_expression_high_bound)
.
6.16:17 A range-to expression is a range expression that specifies an excluded range expression high bound.
6.16:18
The type of a range-to expression is core::ops::RangeTo
.
6.16:19
The value of a range-to expression is
core::ops::RangeTo { end: range_expression_high_bound }
.
6.16:20 A range-to-inclusive expression is a range expression that specifies an included range expression high bound.
6.16:21
The type of a range-to-inclusive expression is
core::ops::RangeToInclusive
.
6.16:22
The value of a range-to-inclusive expression is
core::ops::RangeToInclusive { end: range_expression_high_bound }
.
Dynamic Semantics
6.16:23 The evaluation of a range expression evaluates its operands in left-to-right order.
Examples
1 ..
42 .. 86
..
dawn ..= dusk
..= 5
6.17. If and If Let Expressions¶
6.17.1. If Expressions¶
Syntax
IfExpression
::= ifSubjectExpression
BlockExpression
ElseExpression
?ElseExpression
::= else (BlockExpression
|IfExpression
|IfLetExpression
)
Legality Rules
6.17.1:1 An if expression is an expression that evaluates either a block expression or an else expression depending on the value of its subject expression.
6.17.1:2 An else expression is an expression that represents either a block expression, an if expression, or an if let expression.
6.17.1:3
The type of the subject expression of an if expression shall be
type bool
.
6.17.1:4 The type of an if expression is the type of its block expression.
6.17.1:5 The value of an if expression is the value of its block expression.
6.17.1:6 The type of an else expression is the type of its block expression, if expression, or if let expression.
6.17.1:7 The value of an else expression is the value of its block expression, if expression, or if let expression.
6.17.1:8 The type of an if expression and the type of an else expression shall be unifiable.
Dynamic Semantics
6.17.1:9 The evaluation of an if expression proceeds as follows:
6.17.1:10 The subject expression is evaluated.
6.17.1:11 If the subject expression evaluated to
true
, then the block expression is evaluated.6.17.1:12 If the subject expression evaluated to
false
and the if expression has an else expression, then the else expression is evaluated.
6.17.1:13 The evaluation of an else expression evaluates its block expression, if expression, or if let expression.
Examples
if age <= 14 {
println!("child");
} else if age <= 24 {
println!("youth");
} else if age <=64 {
println!("adult");
} else {
println!("senior");
}
6.17.2. If Let Expressions¶
Syntax
IfLetExpression
::= if letPattern
=SubjectLetExpression
BlockExpression
ElseExpression
?
Legality Rules
6.17.2:1 An if let expression is an expression that evaluates either a block expression or an else expression depending on whether its pattern can be matched against its subject let expression.
6.17.2:2 The expected type of the pattern is the type of the subject let expression.
6.17.2:3 The type of an if let expression is the type of its block expression.
6.17.2:4 The value of an if let expression is the value of its block expression.
6.17.2:5 The type of an if let expression and the type of an else expression shall be unifiable.
Dynamic Semantics
6.17.2:6 The evaluation of an if let expression of the form
if let pattern = subject_let_expression {
/* body */
}
6.17.2:7 is equivalent to the evaluation of the following match expression:
match subject_let_expression {
pattern => { /* body */ },
_ => ()
}
6.17.2:8 The evaluation of an if let expression of the form
if let pattern = subject_let_expression {
/* body */
} else {
/* else */
}
6.17.2:9 is equivalent to the evaluation of the following match expression:
match subject_let_expression {
pattern => { /* body */ },
_ => { /* else */ }
}
Examples
let dish = ("Ham", "Eggs");
if let ("Ham", side) = dish {
println!("Ham is served with {}", side);
}
6.18. Match Expressions¶
Syntax
MatchExpression
::= matchSubjectExpression
{InnerAttributeOrDoc
*MatchArmList
? }MatchArmList
::=IntermediateMatchArm
*FinalMatchArm
IntermediateMatchArm
::=MatchArmMatcher
=> (ExpressionWithBlock
,? |ExpressionWithoutBlock
, )FinalMatchArm
::=MatchArmMatcher
=>Operand
,?MatchArmMatcher
::=OuterAttributeOrDoc
*Pattern
MatchArmGuard
?MatchArmGuard
::= ifOperand
Legality Rules
6.18:1 A match expression is an expression that tries to match one of its multiple patterns against its subject expression and if it succeeds, evaluates an operand.
6.18:2 A match arm is a construct that consists of a match arm matcher and a match arm body.
6.18:3 An intermediate match arm is any non-final match arm of a match expression.
6.18:4 A final match arm is the last match arm of a match expression.
6.18:5 A match arm matcher is a construct that consists of a pattern and a match arm guard.
6.18:6 The expected type of the pattern of the match arm matcher is the type of the subject expression.
6.18:7 A match arm body is the operand of a match arm.
6.18:8 A match arm guard is a construct that provides additional filtering to a match arm matcher.
6.18:9 Bindings introduced in the pattern of a match arm matcher are immutable in the match arm guard.
6.18:10 The type of the subject expression and the types of all patterns of all match arm matchers shall be unifiable.
6.18:11
The type of the operand of a match arm guard shall be type
bool
.
6.18:12 The types of all match arm bodies shall be unifiable.
6.18:13 The type of a match expression is the unified type of the types of the operands of all match arms.
6.18:14
A match arm is selected when its pattern matches the
value of the subject expression and its match arm guard (if any) evaluates to
true
.
6.18:15 Match arm selection happens in declarative order.
6.18:16 The patterns of all match arms taken together shall exhaustively match the subject expression's type.
6.18:17 The value of a match expression is the value of the operand of the selected match arm.
Dynamic Semantics
6.18:18 The evaluation of a match expression proceeds as follows:
6.18:19 The subject expression is evaluated.
6.18:20 Each match arm is evaluated in declarative order as follows:
6.18:21 The match arm matcher of the match arm is evaluated.
6.18:22 If the match arm matcher succeeds, then
6.18:24 Control stops the evaluation of the match expression.
6.18:25 Otherwise control proceeds with the evaluation of the next match arm.
6.18:26 The evaluation of a match arm matcher proceeds as follows:
6.18:27 The pattern of the match arm matcher is evaluated.
6.18:28 If the pattern succeeds, then
6.18:29 If the match arm matcher has a match arm guard, then
6.18:30 The match arm guard is evaluated.
6.18:31 If the match arm guard evaluates to
true
, then the match arm matcher succeeds.
6.18:32 Otherwise the match arm matcher fails.
6.18:33 Otherwise the match arm matcher fails.
6.18:34
The evaluation of a match arm guard evaluates its operand. A
match arm guard evaluates to true
when its operand evaluates to
true
, otherwise it evaluates to false
.
Examples
fn quantify(number_of_things: i32) {
match number_of_things {
0 | 1 => println!("not many"),
2 ..= 9 => println!("a few"),
_ if number_of_things < 0 => println!("you owe me"),
_ => println!("lots")
}
}
6.19. Return Expressions¶
Syntax
ReturnExpression
::= returnExpression
?
Legality Rules
6.19:1 A return expression is an expression that optionally yields a value and causes control flow to return to the end of the enclosing control flow boundary.
6.19:2 A return expression shall appear within a control flow boundary.
6.19:3 The type of a return expression is the never type.
6.19:4 The value returned by a return expression is determined as follows:
6.19:5 If the return expression has an operand, then the value is the value of the operand.
6.19:6 If the return expression does not have an operand, then the value is the unit value.
Dynamic Semantics
6.19:7 The evaluation of a return expression proceeds as follows:
6.19:8 If the return expression has an operand, then
6.19:11 Control destroys the current activation frame.
6.19:12 Control is transferred to the caller frame.
Examples
fn max(left: i32, right: i32) -> i32 {
if left > right {
return left;
}
return right;
}
6.20. Await Expressions¶
Syntax
AwaitExpression
::=FutureOperand
. awaitFutureOperand
::=Operand
Legality Rules
6.20:1 An await expression is an expression that polls a future, suspending the execution of the future until the future is ready.
6.20:2 A future operand is an operand whose future is being awaited by an await expression.
6.20:3 An await expression shall appear within an async control flow boundary. Only the innermost control flow boundary shall be considered.
6.20:4
The type of a future operand shall implement the
core::future::IntoFuture
trait.
6.20:5
The type of an await expression is
<_ as core::future::IntoFuture>::Output
.
6.20:6
The value of an await expression is the value held by
core::task::Poll::Ready
.
Dynamic Semantics
6.20:7 The evaluation of an await expression proceeds as follows:
6.20:8 The future operand is evaluated to a temporary by invoking
core::future::IntoFuture::into_future
with the future operand.6.20:9 The temporary is pinned using
core::pin::Pin::new_unchecked
.6.20:10 The pinned temporary is polled using
core::future::Future::poll
, passing in thecore::task::Context
of the current task.6.20:11 If
core::future::Future::poll
returnscore::task::Poll::Pending
, then the current future yields.6.20:12 If
core::future::Future::poll
returnscore::task::Poll::Ready
, then6.20:13 The value held within is unwrapped.
6.20:14 Control stops the evaluation of the await expression.
Examples
let future = async { expensive_function() };
future.await;
6.21. Expression Precedence¶
Legality Rules
6.21:1 Certain expressions are subject to precedence and associativity.
6.21:2 Precedence is the order by which expressions are evaluated in the presence of other expressions.
6.21:3 Associativity is the order by which operands are evaluated within a single expression.
6.21:4 The precedence and associativity of qualifying expressions are as follows:
6.21:5 |
Expression |
Precedence |
Associativity |
6.21:6 |
highest |
none |
|
6.21:7 |
none |
||
6.21:8 |
left-to-right |
||
6.21:9 |
none |
||
6.21:10 |
none |
||
6.21:11 |
none |
||
6.21:12 |
left-to-right |
||
6.21:13 |
left-to-right |
||
6.21:14 |
left-to-right |
||
6.21:15 |
left-to-right |
||
6.21:16 |
left-to-right |
||
6.21:17 |
left-to-right |
||
6.21:18 |
left-to-right |
||
6.21:19 |
requires parentheses |
||
6.21:20 |
left-to-right |
||
6.21:21 |
left-to-right |
||
6.21:22 |
requires parentheses |
||
6.21:23 |
right-to-left |
||
6.21:24 |
lowest |
none |
6.22. Capturing¶
Legality Rules
6.22:1 A capturing expression is either an async block expression or a closure expression.
6.22:2 A capture target is either a variable or a field of a variable.
6.22:3 The capturing environment of a capturing expression consists of the values of all captured capture targets.
6.22:4 Capturing is the process of saving the capture targets of a capturing expression's capturing environment.
6.22:5 A capture target requires capturing when it is used by the capturing expression and it is defined outside of the capturing expression. Such a capture target is said to be captured.
6.22:6 Capture mode is the mechanism by which a capture target is captured.
6.22:7 A captured capture target with capture mode by value capture passes the value of the capture target into the capturing environment.
6.22:8 A captured capture target with capture mode by immutable reference capture binds an immutable reference to the capture target and passes the immutable reference into the capturing environment.
6.22:9 A captured capture target with capture mode by mutable reference capture binds a mutable reference to the capture target and passes the mutable reference into the capturing environment.
6.22:10 A captured capture target with capture mode by unique immutable reference capture binds a unique immutable reference to the capture target and passes the mutable reference into the capturing environment.
6.22:11 The capture mode is determined based on the use of the capture target within the capturing expression, as follows:
6.22:12 If the capturing expression is subject to keyword
move
, then the capture mode is by value capture.6.22:13 Otherwise the capture mode is determined based on the following precedence:
6.22:14 By immutable reference capture.
6.22:15 By unique immutable reference capture mode, if the capture target is a mutable reference that is being modified.
6.22:16 By mutable reference capture mode.
6.22:17 By value capture.
6.22:18 A tool selects the first capture mode that is compatible with the use of the capture target.
6.23. Arithmetic Overflow¶
6.23:1 An arithmetic overflow occurs when an operator expression computes a value of a scalar type that lies outside of the range of valid values for the scalar type or when one or more operand of an operator expression lies outside of the range of valid values for the operation.
Dynamic Semantics
6.23:2 There are two allowed behaviors for arithmetic overflow:
6.23:3 Evaluation of the expression may result in a panic.
6.23:4 The resulting value of the expression may be truncated, discarding the most significant bits that do not fit in the target type.