为什么Option类型的try块需要类型注解?

4
编译器:rustc 1.71.0-nightly (c609da59d 2023-04-18)
我尝试了夜版的#![feature(try_blocks)],使用了以下代码:
#![feature(try_blocks)]
fn test_try(input: Option<i32>) {
    let output = try {
        input?
    };

    println!("{:?}", output);
}

但编译器声称output需要类型注释。完整的错误信息如下:
error[E0282]: type annotations needed
 --> src/main.rs:3:9
  |
3 |     let output = try {
  |         ^^^^^^
  |
help: consider giving `output` an explicit type
  |
3 |     let output: /* Type */ = try {
  |               ++++++++++++

如果我尝试使用let output: Option<i32> = ...一切都正常。
看起来output应该是Option<i32>,但编译器没有推断出来。
这是因为这个特性不稳定,还是我漏掉了什么?output除了Option<i32>之外还可能是其他类型吗?
1个回答

9

try_blocks 功能因为推断问题而不太稳定。Try 特性的设计(支持 try 块和 ? 运算符)使其非常灵活,但也让编译器很难推断出类型。

在 std 中,除了 Option<i32> 之外,没有其他可以作为表达式结果的类型。但是,我们可以自己编写一个类型,因为驱动 try 块展开的不是其中的 ? 类型,而是它最终的类型。因此,它可以是任何支持对 Option<i32> 进行 ? 操作的类型。例如:

#![feature(try_blocks, try_trait_v2)]

use std::convert::Infallible;
use std::ops::ControlFlow;

#[derive(Debug)]
struct MyFancyType;

impl std::ops::FromResidual<Option<Infallible>> for MyFancyType {
    fn from_residual(_residual: Option<Infallible>) -> Self {
        Self
    }
}

impl std::ops::FromResidual for MyFancyType {
    fn from_residual(_residual: Infallible) -> Self {
        Self
    }
}

impl std::ops::Try for MyFancyType {
    type Output = i32;
    type Residual = Infallible;

    fn from_output(_output: i32) -> Self {
        Self
    }

    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        ControlFlow::Continue(0)
    }
}

fn test_try(input: Option<i32>) {
    let output: MyFancyType = try { input? };

    println!("{:?}", output);
}

游乐场


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接