Why can a Rust struct be defined without a semicolon?

懵懂的女人 提交于 2020-05-09 06:26:08

问题


I'm learning Rust and the chapter for structs gives an example of a struct without a ; at the end. It compiles but I have no idea why this is allowed.

fn main() {
    struct User {
        username: String,
        email: String,
        sign_in_count: u64,
        active: bool,
    }
}

... same question goes for functions, actually.


回答1:


As Shepmaster said in the comment, the "reason" is that Rust defines so. Here I will explain the rules behind it.

Basically you can omit ; when it ends with }. This will answer your question.

However, there are a number of exceptions to the rule:

When {} appears indirectly

The rule above doesn't apply when {} appears indirectly, like

use std::io::{self, Read, Write}; // Here }; appears

or

let x = if cond {
    1
} else {
    2
}; // Here }; appears

In this case, {} isn't a direct part of use/let. So in this case you need ;.

Items

Items are things which you can also place outside of functions. That is, one of extern crate, use, mod, struct, enum, union, type, trait, impl, fn, static, const, extern, and macros.

You can place items either outside of functions or in a function. However, There is a difference between them:

  • If it appears outside of functions, you have to omit ; when unnecessary.
  • If it appears in a function, you can also place ; there. This is basically because the ; itself is an empty statement.

Example:

struct A {} // You can't place ; here
fn main() {
    struct B {} // You can omit ; here
    struct C {}; // You can also place ; here
}

The last expression

You have to omit ; if

  • It is the last statement in the block,
  • it is an expression (items and let aren't expressions), and
  • you want to return the value from the expression.

Example:

fn f() -> i32 {
    let x = 1;
    x + x // You want to return x + x, so you can't place `;` here
}

Block expressions

if, if let, match, loop, while, while let, for, unsafe, and bare {} ends with }, so you can omit ; after them. However, there is a slight effect if you place ; here.

Example:

fn f(x: i32) -> i32 {
    if x < 10 {
        10
    } else {
        20
    }; // If you remove ; here, then you will see a compile error.
    42
}

In most cases, you don't have to place ; here; instead you may have to place ; in the blocks.

fn f(x: i32) -> i32 {
    if x < 10 {
        10;
    } else {
        20;
    }
    42
}

Statement macros

In statement positions, you can write three different kinds of macros:

  • some_macro!()/some_macro![]: this isn't in fact a statement macro; instead, this is a mere expression macro. It can't expand to items or let.
  • some_macro!{}: this expands to zero or more statements.
  • some_macro!();/some_macro![];/some_macro!{};: this also expands to zero or more statements; however, there is a very minor difference: ; is added to the last expanded statement.


来源:https://stackoverflow.com/questions/44990058/why-can-a-rust-struct-be-defined-without-a-semicolon

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!