我有一个匹配表达式,希望从中返回错误。似乎编译器无法推断出最后一种情况e
是Err(String)
,并且要求模式是明确的:
fn foo() -> Result<Option<u8>, String> {
unimplemented!() // don't mind the panic here
}
fn foo2() -> Result<u8, String> {
let bar = foo();
for _ in 0..3 {
let baz = match bar {
Ok(Some(b)) => b,
Ok(None) => continue,
Err(e) => return Err(e) // works
// e => return e // error[E0308]
};
}
Ok(0)
}
fn main() {
let _ = foo2();
}
错误是:
error[E0308]: mismatched types
--> src/main.rs:13:33
|
13 | e => return e // error[E0308]
| ^ expected u8, found enum `std::option::Option`
|
= note: expected type `std::result::Result<u8, _>`
found type `std::result::Result<std::option::Option<u8>, _>`
我很确定我已经用尽了所有Ok(_)
个变体,因此剩下的唯一一个应该是Err(_)
。例如,如果foo()
返回Result<u8, String>
,则不会发生此错误。我想念什么吗?
答案 0 :(得分:8)
因为Err
不是类型。
Err
是Result<T, E>
的变体,其类型为Result<T, E>
。由于Result<T, E>
除Result<U, E>
之外与T == U
不同,并且由于没有隐式转换,因此您需要显式执行转换。
我承认它看起来确实很愚蠢,因为类型推断会推论得出T
,U
和E
,但在语义上这2个Err(e) => return Err(e)
的级别不同。
再举一个愚蠢的例子:
Err(e)
由于相同的原因将失败,因为enum Term<'a> {
Int(i64),
String(&'a str),
}
fn staticify(t: Term) -> Term<'static> {
use Term::*;
match t {
String(_) => String("Hello, World!"),
_ => t,
}
}
和Term<'a>
的类型不同,除非Term<'static>
。当'a == 'static
主要包含非生命周期参数时,它会变得很乏味:(
答案 1 :(得分:3)
如果您对Err(e) => return Err(e)
案例使用合格的类型,事情将会更加清楚。您在这里真正说的是:
Result<Option<u8>, String>::Err(e) => return Result<u8, String>::Err(e)
这样编写后,很明显正在进行转换。相反,e => return e
等效于:
Result<Option<u8>, String>::Err(e) => return Result<Option<u8>, String>::Err(e)
类型错误,因为您的函数应该返回Result<u8, String>
。
答案 2 :(得分:2)
您要匹配Result<Option<u8>, String>
,因此e
属于这种类型,但是您的函数要求返回值必须是Result<u8, String>
的类型:
note: expected type `std::result::Result<u8, _>`
found type `std::result::Result<std::option::Option<u8>, _>`