Compiler error when return expression ends with `as`

I encountered this syntax error today:

fn compiler_error() -> u32 {
    if true {
        4i32
    } else {
        5i32
    } as u32
}
error: expected expression, found `as`
 --> src/lib.rs:7:7
  |
7 |     } as u32
  |       ^^ expected expression
  |
help: parentheses are required to parse this as an expression
  |
3 ~     (if true {
4 |         4i32
5 |     } else {
6 |         5i32
7 ~     }) as u32
  |

This seems unintuitive (granted, I've only been working in Rust for six months).

  • In this case, is requiring parentheses a bug?
  • If not, what is the reasoning for the requirement? Variable assignments do not require them:
    fn alternative_fix() -> u32 {
        let foo = if true {
            4i32
        } else {
            5i32
        } as u32;
        foo
    }
    

(Playground)

This has nothing to do with being the trailing/return expression; this is because the if-else is a block-like expression which is treated as a statement here. In the case of let $pat = if ..., the if-else is in expression position where statements are not valid, so is unambiguously considered an expression, not a statement.

It's the case that when an operator is valid both as prefix and infix (e.g. -), writing if true { a } else { b } - c is parsed as the statement if true { a } else { b }; and then the expression -c. This is stable behavior and cannot be changed. To avoid potentially confusing inconsistencies, other infix operator-likes such as as do not cause the if-else to not be a statement.

This behavior is why you don't need a ; after a statement if-else.

11 Likes