70 %
Chris Biscardi

Are functions in Rust statements or expressions?

Function bodies contain statements and expressions. ; can turn an expression into a statement. So is a function definition itself a statement or an expression? It doesn't have a semicolon on it.

rust
fn something(a: i32) -> i32 {
a + 2
}

If we look at the function reference we can see the syntax laid out as such:

Syntax
Function :
FunctionQualifiers fn IDENTIFIER Generics?
( FunctionParameters? )
FunctionReturnType? WhereClause?
BlockExpression
FunctionQualifiers :
AsyncConstQualifiers? unsafe? (extern Abi?)?
AsyncConstQualifiers :
async | const
Abi :
STRING_LITERAL | RAW_STRING_LITERAL
FunctionParameters :
FunctionParam (, FunctionParam)* ,?
FunctionParam :
OuterAttribute* Pattern : Type
FunctionReturnType :
-> Type

The way this reads is that a Function is the following, in order:

  1. some FunctionQualifiers
    • we have none
  2. the letters fn
  3. an IDENTIFIER
    • something in our example above
  4. optionally some Generics?
    • we have none
  5. potentially multiple parameters ( FunctionParameters? ) (sometimes also called arguments)
    • a: i32 is our only parameter
  6. an optional FunctionReturnType?
    • we return an i32 using -> i32
  7. an optional WhereClause?
    • we have none
  8. a BlockExpression
    • this is the interesting part

The final piece is a BlockExpression. So a function is some stuff followed by a block expression.

That doesn't fully answer our question though. Let's take a look at the definition of syntax for Statements:

Syntax
Statement :
;
| Item
| LetStatement
| ExpressionStatement
| MacroInvocationSemi

A Statement is any one of these things. In our case, we only care about Item (whose syntax is a bit more complicated). A Function declaration, it turns out, is an Item.

In the end a Function is an Item which is a Statement, so functions are statements and thus don't need ; on the end of a function declaration.