块表达式
语法
块表达式 :
{
内部属性*
语句组?
}
块表达式 或 块 是控制流表达式和用于条目和变量声明的匿名命名空间作用域。
对于控制流表达式,块按顺序执行其组成的非条目声明语句,然后执行其最后的可选表达式。
在块匿名命名空间作用域内部的条目声明,对于块本身可用,而由 let 语句声明的变量从下一条语句开始到块结束之前可用。
块的语法是 { ,然后是 内部属性 ,以及任意数量的 语句 ,随后是一个可选的表达式,称为最终操作数,和 } 。
语句通常需要在分号后面,有两个例外:
- 条目声明语句不需要在分号后面。
 - 表达式语句通常需要分号,除非其外围表达式是控制流表达式。
 
此外,语句之间允许有额外的分号,但不影响语义。
在评估块表达式时,除条目声明语句外,每个语句都按顺序执行。 然后,如果给定了最终操作数,则执行它。
块的类型是最终操作数的类型,如果省略,则为 () 。
#![allow(unused)] fn main() { fn fn_call() {} let _: () = { fn_call(); }; let five: i32 = { fn_call(); 5 }; assert_eq!(5, five); }
注意: 对于控制流表达式,如果块表达式是表达式语句的外围表达式,则期望的类型是
(),除非它紧跟着一个分号。
块始终是值表达式,并在值表达式上下文中计算最终操作数。
注意: 如果确实需要,这一特性可用于强制移动值。例如,以下示例在调用
consume_self时失败,因为结构体已在块表达式中移动了s。#![allow(unused)] fn main() { struct Struct; impl Struct { fn consume_self(self) {} fn borrow_self(&self) {} } fn move_by_block_expression() { let s = Struct; // 在块表达式中将值从 `s` 移出。 (&{ s }).borrow_self(); // 无法执行,因为 `s` 已经被移出了。 s.consume_self(); } }
async 块
语法
Async块表达式 :
asyncmove? 块表达式
异步块是块表达式的一种变体,值求解为一个 future 。 块的最终表达式 (如果存在) 确定 future 的结果值。
执行异步块类似于执行闭包表达式: 
它的即时效果是生成并返回一个匿名类型。
返回实现一个或多个 std::ops::Fn trait 的类型,异步块返回的类型实现了 std::future::Future trait。
这种类型的实际数据格式是未指明的。
注意: rustc 生成的 future 类型大致相当于具有每个
await点一个变体的枚举类型,其中每个变体存储从其相应点恢复所需的数据。 版本差异: 异步块仅在 Rust 2018 及以后版本中可用。
捕获模式
异步块使用与闭包相同的 捕获模式 从环境中捕获变量。
与闭包一样,当写成 async { .. } 时,每个变量的捕获模式将从块的内容推断。
然而, async move { .. } 块将移动所有被引用的变量到生成的 future 中。
异步上下文
由于异步块构造了一个 future ,其定义了一个 异步上下文 ,这个上下文可以包含 await 表达式 。
异步上下文由异步块以及异步函数的函数体构建,异步函数的语义是以异步块为基础进行定义的。
控制流运算符
异步块有类似于函数的约束,就像闭包一样。
因此, ? 运算符和 return 表达式都会影响 future 的输出,而不是封闭函数或其他上下文。
也就是说,从异步块中的 return <expr> 将返回 <expr> 的结果作为 future 的输出。
同样,如果 <expr>? 传播错误,则该错误将作为 future 的结果传播。
最后, break 和 continue 关键字不能用于从异步块中分支跳出。
以下代码是非法的:
#![allow(unused)] fn main() { loop { async move { break; // error[E0267]: `break` inside of an `async` block } } }
unsafe 块
语法
Unsafe块表达式 :
unsafe块表达式
在需要进行 unsafe 操作 时,可在块之前添加 unsafe 关键字。详见 unsafe 块 。
示例:
#![allow(unused)] fn main() { unsafe { let b = [13u8, 17u8]; let a = &b[0] as *const u8; assert_eq!(*a, 13); assert_eq!(*a.offset(1), 17); } unsafe fn an_unsafe_fn() -> i32 { 10 } let a = unsafe { an_unsafe_fn() }; }
块表达式标签
在 循环和其他可中断表达式 部分进行了说明。
块表达式上的属性
在以下情况下,可以在块表达式的左括号之后直接使用 内部属性 :
- 函数 和 方法 体。
 - 循环体 ( 
loop、while、while let和for)。 - 作为 语句 使用的块表达式。
 - 块表达式作为 数组表达式 、 元组表达式 、 调用表达式 和类似元组的 结构体 表达式的元素。
 - 另一个块表达式的尾表达式是块表达式。
 
在块表达式上具有含义的外围属性包括 cfg 和 代码分析检查属性 。
例如,以下函数在 Unix 平台上返回 true ,在其他平台上返回 false 。
#![allow(unused)] fn main() { fn is_unix_platform() -> bool { #[cfg(unix)] { true } #[cfg(not(unix))] { false } } }