What is expr.? What is stmt.?

fn main( )-> <T>  {
   <T>               // is it expr. ?
}

fn main( ) -><T> {
   return <T> ;      // is it stmt. ?
}

So, what is it? Statement or expression ?

What is what? Statements are statements, expressions are expressions, and they can mutually contain each other. Eg. there are statements containing expressions, and there are expressions that can contain statements (such as blocks).

2 Likes

To me, In my example ... and return ... ? are the same, if so, it is strange to call its differently (expr. and stmt. are not synonyms, are its?)

A <T> all by its own isn't valid syntax in Rust.

If you want a formal definition of the difference between expressions and statements, check out the Rust reference

Statements: Statements - The Rust Reference

Expressions: Expressions - The Rust Reference

4 Likes

There are exactly two kinds of statement in Rust:

  • Declarations (e.g. let, fn, struct)
  • Expression statements (i.e. an expression, followed by a semi-colon)

That's it - pretty much everything else is an expression.

To go back to your example:

fn main() -> i32 {
   return 123;
}
  • 123 is an expression.
  • return 123 is an expression.
  • return 123; is a statement.

A block (such as the body of a function) can either end with an expression or a statement. If it ends with an expression, that is the return value of that block.

12 Likes

No, they aren't. It is not the case that all expressions automatically make the function return (that would make it impossible to usefully write functions with more than one expression). It is the case that the last expression of a block is the value of that block, but there is a very marked difference as soon as you start writing multiple expressions and statements in a function.

1 Like

I have a question about this. Consider this code:

fn abs(x: i32) -> i32 {
    if x > 0 {
        x
    } else {
        -x
    }
}

The body of the function is a block expression. According to the reference, a block expression contains a list of statements, optionally followed by an "ExpressionWithoutBlock", called the "final operand":

The syntax for a block is { , then any inner attributes, then any number of statements, then an optional expression, called the final operand, and finally a } .

Well clearly an "if" expression is not an "ExpressionWithoutBlock". So this would imply that "if" here is an expression statement, right?

This is further confirmed by the page about statements:

An expression that consists of only a block expression or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon. This can cause an ambiguity between it being parsed as a standalone statement and as a part of another expression; in this case, it is parsed as a statement.

All this confirms that the block in my abs function does not have a "final operand", right?

But then, the reference says that:

An expression statement is one that evaluates an expression and ignores its result.

and also

The type of a block is the type of the final operand, or () if the final operand is omitted.

So this would imply that the type of the block in my function is ().

So how come the abs function compiles?

2 Likes

This appears to be an error in the reference. The Ferrocene spec says that the last item in a block is any expression, which agrees with my experience of how the compiler works. There is probably an ambiguity in their formal grammar, however, as there are character strings that can be interpreted as either statements or expressions.

2 Likes

Yes I agree that the Ferrocene grammar seems ambiguous for my example.

I filed a Ferrocene GitHub issue for this.

1 Like