Rust允许单async块却拒if-else同结构async块的原因
底层成因
这个编译差异和async块里的return关键字无关——哪怕把两个async块里的return替换成(),第二段代码依然会报完全相同的错误,核心来自Rust的两个确定性规则:
- 每个独立定义的
async {}块,编译时都会生成全局唯一的匿名类型,该类型实现了Futuretrait。哪怕两个async块的代码完全一致,它们也是完全不同的类型,不存在类型兼容性。这个规则和闭包完全一致:哪怕两个闭包的签名、逻辑逐行相同,也属于不同类型。 - Rust的
if/else是表达式,强制要求所有分支的返回值为完全相同的类型,编译器会以首个分支的返回类型为基准,校验其余分支的类型是否匹配。
第一段代码编译通过的原因
第一段代码的闭包体内仅存在一个async块,没有多分支类型统一的需求:编译器直接将闭包的返回类型推断为这一个async块对应的匿名Future类型,全程无类型冲突,因此可以正常编译。
第二段代码编译失败的原因
第二段代码中,if分支返回第一个async块的匿名类型,else分支返回第二个async块的独立匿名类型。编译器做分支类型校验时,发现两个类型不匹配,就会抛出E0308错误。报错信息里的expected 'async' block, found a different 'async' block,已经直接说明两个async块属于不同类型。
如果需要让第二段代码通过编译,可以对两个分支的Future做类型擦除,统一为相同的动态分发Future类型,比如用Box::pin将两个async块都包装为Pin<Box<dyn Future<Output = ()>>>即可。
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

