Caution

You’re reading a draft of the Ferrocene Language Specification. Some parts of this document might be missing, incomplete or incorrect. Our aim is to have the specification ready by the end of 2022.

6. Expressions

Syntax

Expression ::=
    ExpressionWithBlock
  | ExpressionWithoutBlock

ExpressionWithBlock ::=
    OuterAttributeOrDoc* (
        AsyncBlockExpression
      | BlockExpression
      | IfExpression
      | IfLetExpression
      | LoopExpression
      | MatchExpression
      | UnsafeBlockExpression
    )

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: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: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:47 It is a static error to create a mutable reference in a constant context.

6.1.2:48 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:49 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:50 A constant expression is evaluated statically whenever its value is needed.

6.1.2:51 The evaluation of a constant expression that results in arithmetic overflow panics.

6.1.2:52 It is a static error if a constant expression either panics or control reaches the invocation of macro core::panic.

Dynamic Semantics

6.1.2:53 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.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:7 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:16 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:17 A place expression context is a construct that may evaluate its operand as a memory location.

6.1.4:18 The following constructs are place expression contexts:

6.1.4:29 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:39 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 ::=
    PathExpression
  | 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 ::=
    Label? {
      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 named block expression is a block expression with a label.

6.4:3 An anonymous block expression is a block expression without a label.

6.4:4 A tail expression is the last expression within a block expression.

6.4:5 The type of a block expression is determined as follows:

6.4:10 The value of a block expression is determined as follows:

Dynamic Semantics

6.4:14 The evaluation of a block expression proceeds as follows:

  1. 6.4:15 Each statement is executed in declarative order.

  2. 6.4:16 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. Unsafe Blocks

Syntax

UnsafeBlockExpression ::=
    unsafe BlockExpression

Legality Rules

6.4.2:1 An unsafe block expression is a block expression that is specified with keyword unsafe.

6.4.2:2 An unsafe block expression allows unsafety.

6.4.2:3 The type of the unsafe block expression is the type of its block expression.

6.4.2:4 The value of the unsafe block expression is the value of its block expression.

Dynamic Semantics

6.4.2: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: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: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 Paragraph 6.4.1. 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:

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:

  1. 6.5.4:9 The operand is evaluated.

  2. 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.

  3. 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

  1. 6.5.4:15 If the type of operand is neither an integer type nor bool, then core::ops::Not::not(operand) is invoked.

6.5.4:16 The evaluation of a negation expression with a SignNegationOperator proceeds as follows:

  1. 6.5.4:17 The operand is evaluated.

  2. 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.

  3. 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.

  4. 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:

  1. 6.5.5:23 The left operand is evaluated.

  2. 6.5.5:24 The right operand is evaluated.

  3. 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.

  4. 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:

  1. 6.5.5:28 The left operand is evaluated.

  2. 6.5.5:29 The right operand is evaluated.

  3. 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.

    1. 6.5.5:31 If unsigned integer division is performed and the right operand is 0, then the operation results in a panic.

    2. 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.

  4. 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:

  1. 6.5.5:35 The left operand is evaluated.

  2. 6.5.5:36 The right operand is evaluated.

  3. 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.

  4. 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:

  1. 6.5.5:40 The left operand is evaluated.

  2. 6.5.5:41 The right operand is evaluated.

  3. 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.

    1. 6.5.5:43 If unsigned integer division is performed and the right operand is 0, then the operation results in a panic.

    2. 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.

  4. 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:

  1. 6.5.5:47 The left operand is evaluated.

  2. 6.5.5:48 The right operand is evaluated.

  3. 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.

  4. 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:

  1. 6.5.6:23 The left operand is evaluated.

  2. 6.5.6:24 The right operand is evaluated.

  3. 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:

  1. 6.5.6:27 The left operand is evaluated.

  2. 6.5.6:28 The right operand is evaluated.

  3. 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:

  1. 6.5.6:31 The left operand is evaluated.

  2. 6.5.6:32 The right operand is evaluated.

  3. 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:

  1. 6.5.6:35 The left operand is evaluated.

  2. 6.5.6:36 The right operand is evaluated.

  3. 6.5.6:37 core::ops::Shl::shl(left_operand, right_operand) is invoked.

6.5.6:38 The evaluation of a shift right expression proceeds as follows:

  1. 6.5.6:39 The left operand is evaluated.

  2. 6.5.6:40 The right operand is evaluated.

  3. 6.5.6:41 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:

  1. 6.5.7:23 The left operand is evaluated.

  2. 6.5.7:24 The right operand is evaluated.

  3. 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:

  1. 6.5.7:27 The left operand is evaluated.

  2. 6.5.7:28 The right operand is evaluated.

  3. 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:

  1. 6.5.7:31 The left operand is evaluated.

  2. 6.5.7:32 The right operand is evaluated.

  3. 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:

  1. 6.5.7:35 The left operand is evaluated.

  2. 6.5.7:36 The right operand is evaluated.

  3. 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:

  1. 6.5.7:39 The left operand is evaluated.

  2. 6.5.7:40 The right operand is evaluated.

  3. 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:

  1. 6.5.7:43 The left operand is evaluated.

  2. 6.5.7:44 The right operand is evaluated.

  3. 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:

  1. 6.5.8:8 The left operand is evaluated.

  2. 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.

  3. 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:

  1. 6.5.8:12 The left operand is evaluated.

  2. 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.

  3. 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 as TypeSpecificationWithoutBounds

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: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:

Examples

6.5.9:41 See Paragraph 6.4.1. 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:

  1. 6.5.10.1:3 The value operand is evaluated.

  2. 6.5.10.1:4 The assignee operand is evaluated.

  3. 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.

  4. 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: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:

Dynamic Semantics

6.5.10.2:16 The evaluation of a destructuring assignment proceeds as follows:

  1. 6.5.10.2:17 The value operand is evaluated.

  2. 6.5.10.2:18 The assignee operand is evaluated by evaluating its operands in a left-to-right order.

  3. 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.

  4. 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:

  1. 6.5.11:27 If the types of both operands are primitive types, then

    1. 6.5.11:28 The modifying operand is evaluated.

    2. 6.5.11:29 The assigned operand is evaluated.

    3. 6.5.11:30 The appropriate function is invoked as indicated below.

  2. 6.5.11:31 Otherwise

    1. 6.5.11:32 The assigned operand is evaluated.

    2. 6.5.11:33 The modifying operand is evaluated.

    3. 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: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:

  1. 6.8:16 If the value of the size operand is greater than zero, then:

    1. 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.

    2. 6.8:18 Otherwise the repeat operand is evaluated size operand's value times.

  2. 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 A 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:10 If the indexed operand is mutable and the index expression is evaluated in a mutable place expression context, then

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:

  1. 6.9:15 The indexed operand is evaluated.

  2. 6.9:16 The indexing operand is evaluated.

  3. 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.

  4. 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, a struct value, or a union 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:26 If the constructee is a tuple enum variant or a tuple struct, then

6.11:31 If the constructee is a union type, then

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:

Dynamic Semantics

6.12.1:14 The evaluation of a call expression proceeds as follows:

  1. 6.12.1:15 The call operand is evaluated.

  2. 6.12.1:16 The argument operands are evaluated in left-to-right order.

  3. 6.12.1:17 If the adjusted call operand is a function item type or function pointer type, then corresponding function is invoked.

  4. 6.12.1:18 If the type of the call operand implements the core::ops::Fn trait, then core::ops::Fn::call(adjusted_call_operand, argument_operand_tuple) is invoked.

  5. 6.12.1:19 If the type of the call operand implements the core::ops::FnMut trait, then core::ops::FnMut::call_mut(adjusted_call_operand, argument_operand_tuple) is invoked.

  6. 6.12.1:20 If the type of the call operand implements the core::ops::FnOnce trait, then core::ops::FnOnce::call_once(adjusted_call_operand, argument_operand_tuple) is invoked.

Undefined Behavior

6.12.1:21 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:

  1. 6.12.2:8 The receiver operand is evaluated.

  2. 6.12.2:9 The argument operands are evaluated in left-to-right order.

  3. 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 when reading the selected field of a union type when it contains invalid data.

Dynamic Semantics

6.13:12 The evaluation of a field access expression evaluates its container operand.

Examples

6.13:13 See Paragraph 6.8.1. 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 A closure body is a construct that represents the executable portion of a closure expression.

6.14:3 A closure body denotes a new control flow boundary.

6.14:4 A closure body is subject to capturing.

6.14:5 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:6 The pattern of a closure parameter shall be an irrefutable pattern.

6.14:7 The type of a closure expression is the unique anonymous closure type defined by it.

6.14:8 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:9 The evaluation of a closure expression proceeds as follows:

  1. 6.14:10 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 ::=
    for Pattern in SubjectExpression 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 type of an for loop expression is the unit type.

6.15.1:4 The value of an for loop expression is the unit value.

Dynamic Semantics

6.15.1:5 The evaluation of a for loop expression of the form

'label: for pattern in subject_expression {
    /* loop body */
}

6.15.1:6 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 ::=
    loop LoopBody

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 a infinite loop expression is determined as follows:

6.15.2:5 The value of a infinite loop expression is determined as follows:

Dynamic Semantics

6.15.2:8 The evaluation of an infinite loop expression proceeds as follows:

  1. 6.15.2:9 The block expression is evaluated.

  2. 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 ::=
    while IterationExpression LoopBody

IterationExpression ::=
    Expression

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 an while loop expression is the unit type.

6.15.3:5 The value of an while loop expression is the unit value.

Dynamic Semantics

6.15.3:6 The evaluation of a while loop expression proceeds as follows:

  1. 6.15.3:7 The iteration expression is evaluated.

  2. 6.15.3:8 If the iteration expression evaluated to true, then:

    1. 6.15.3:9 The block expression is evaluated.

    2. 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 let Pattern = 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 type of an while let loop expression is the unit type.

6.15.4:3 The value of an while let loop expression is the unit value.

Dynamic Semantics

6.15.4:4 The evaluation of a while let loop expression of the form

'label: let pattern = subject_let_expression {
    /* loop body */
}

6.15.4:5 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 ::=
    break LabelIndication? 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:13 Break value is the value of the operand of a break expression.

6.15.6:14 The break value is determined as follows:

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:

  1. 6.15.6:18 The operand is evaluated.

  2. 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:

  1. 6.15.6:21 The operand is evaluated.

  2. 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 ::=
    continue LabelIndication?

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:

  1. 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.

  2. 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 ::=
    if SubjectExpression 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:

  1. 6.17.1:10 The subject expression is evaluated.

  2. 6.17.1:11 If the subject expression evaluated to true, then the block expression is evaluated.

  3. 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 let Pattern = 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 type of an if let expression is the type of its block expression.

6.17.2:3 The value of an if let expression is the value of its block expression.

6.17.2:4 The type of an if let expression and the type of an else expression shall be unifiable.

Dynamic Semantics

6.17.2:5 The evaluation of an if let expression of the form

if let pattern = subject_let_expression {
    /* body */
}

6.17.2:6 is equivalent to the evaluation of the following match expression:

match subject_let_expression {
    pattern => { /* body */ },
    _ => ()
}

6.17.2:7 The evaluation of an if let expression of the form

if let pattern = subject_let_expression {
    /* body */
} else {
    /* else */
}

6.17.2:8 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 ::=
    match SubjectExpression {
      InnerAttributeOrDoc*
      MatchArmList?
    }

MatchArmList ::=
    IntermediateMatchArm* FinalMatchArm

IntermediateMatchArm ::=
    MatchArmMatcher =>
      ( ExpressionWithBlock ,? | ExpressionWithoutBlock , )

FinalMatchArm ::=
    MatchArmMatcher => Operand ,?

MatchArmMatcher ::=
    OuterAttributeOrDoc* Pattern MatchArmGuard?

MatchArmGuard ::=
    if Operand

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 A match arm body is the operand of a match arm.

6.18:7 A match arm guard is a construct that provides additional filtering to a match arm matcher.

6.18:8 Bindings introduced in the pattern of a match arm matcher are immutable in the match arm guard.

6.18:9 The type of the subject expression and the types of all patterns of all match arm matchers shall be unifiable.

6.18:10 The type of the operand of a match arm guard shall be type bool.

6.18:11 The types of all match arm bodies shall be unifiable.

6.18:12 The type of a match expression is the unified type of the types of the operands of all match arms.

6.18:13 A match arm is selected when its pattern matches the subject expression and its match arm guard (if any) evaluates to true.

6.18:14 Match arm selection happens in declarative order.

6.18:15 The patterns of all match arms taken together shall exhaustively match the subject expression's type.

6.18:16 The value of a match expression is the value of the operand of the selected match arm.

Dynamic Semantics

6.18:17 The evaluation of a match expression proceeds as follows:

  1. 6.18:18 The subject expression is evaluated.

  2. 6.18:19 Each match arm is evaluated in declarative order as follows:

    1. 6.18:20 The match arm matcher of the match arm is evaluated.

    2. 6.18:21 If the match arm matcher succeeds, then

      1. 6.18:22 The operand of the match arm is evaluated.

      2. 6.18:23 Control stops the evaluation of the match expression.

    3. 6.18:24 Otherwise control proceeds with the evaluation of the next match arm.

6.18:25 The evaluation of a match arm matcher proceeds as follows:

  1. 6.18:26 The pattern of the match arm matcher is evaluated.

  2. 6.18:27 If the pattern succeeds, then

    1. 6.18:28 If the match arm matcher has a match arm guard, then

      1. 6.18:29 The match arm guard is evaluated.

      2. 6.18:30 If the match arm guard evaluates to true, then the match arm matcher succeeds.

    2. 6.18:31 Otherwise the match arm matcher fails.

  3. 6.18:32 Otherwise the match arm matcher fails.

6.18:33 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 ::=
    return Expression?

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:

Dynamic Semantics

6.19:7 The evaluation of a return expression proceeds as follows:

  1. 6.19:8 If the return expression has an operand, then

    1. 6.19:9 The operand is evaluated.

    2. 6.19:10 The value of the operand is passed by move into the designated output location of the enclosing control flow boundary.

  2. 6.19:11 Control destroys the current activation frame.

  3. 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 . await

FutureOperand ::=
    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:

  1. 6.20:8 The future operand is evaluated to a temporary by invoking core::future::IntoFuture::into_future with the future operand.

  2. 6.20:9 The temporary is pinned using core::pin::Pin::new_unchecked.

  3. 6.20:10 The pinned temporary is polled using core::future::Future::poll, passing in the core::task::Context of the current task.

  4. 6.20:11 If core::future::Future::poll returns core::task::Poll::Pending, then the current future yields.

  5. 6.20:12 If core::future::Future::poll returns core::task::Poll::Ready, then

    1. 6.20:13 The value held within is unwrapped.

    2. 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

Array expression

Block expression

Continue expression

If expression

If let expression

Literal expression

Loop expression

Match expression

Parenthesized expression

Path expression

Struct expression

Tuple expression

Underscore expression

highest

none

6.21:7

Method call expression

none

6.21:8

Await expression

Field access expression

left-to-right

6.21:9

Call expression

Index expression

none

6.21:10

Error propagation expression

none

6.21:11

Borrow expression

Dereference expression

Negation expression

none

6.21:12

Type cast expression

left-to-right

6.21:13

Division expression

Multiplication expression

Remainder expression

left-to-right

6.21:14

Addition expression

Subtraction expression

left-to-right

6.21:15

Shift left expression

Shift right expression

left-to-right

6.21:16

Bit and expression

left-to-right

6.21:17

Bit xor expression

left-to-right

6.21:18

Bit or expression

left-to-right

6.21:19

Comparison expression

requires parentheses

6.21:20

Lazy and expression

left-to-right

6.21:21

Lazy or expression

left-to-right

6.21:22

Range expression

requires parentheses

6.21:23

Assignment expression

Compound assignment expression

right-to-left

6.21:24

Break expression

Closure expression

Return expression

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 copy 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:

  1. 6.22:12 If the capturing expression is subject to keyword move, then the capture mode is by value capture.

  2. 6.22:13 Otherwise the capture mode is determined based on the following precedence:

    1. 6.22:14 By immutable reference capture.

    2. 6.22:15 By unique immutable reference capture mode, if the capture target is a mutable reference that is being modified.

    3. 6.22:16 By mutable reference capture mode.

    4. 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 arithmetic expression or a negation expression computes a value of a scalar type that lies outside of the range of valid values for the scalar type.

Dynamic Semantics

6.23:2 There are two allowed behaviors for arithmetic overflow:

  1. 6.23:3 Evaluation of the expression may result in a panic.

  2. 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.