问题
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
letaren'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 orlet.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