假设有一个外部模块(由第三方库提供):
pub mod external_module {
#[derive(Debug)]
pub struct ExternalError;
pub trait SomeTrait {
fn do_stuff(&self) -> Result<i32, ExternalError>;
}
}
我需要在代码中使用SomeTrait
。我的代码可能会遇到一些内部错误,因此我定义了自己的错误类型并将其转换为ExternalError
:
struct MyError;
impl Into<ExternalError> for MyError {
fn into(self) -> external_module::ExternalError {
ExternalError {}
}
}
请注意,由于from<MyError> for ExternalError
是在我的名称空间之外定义的(实际上甚至是在我的板条箱之外),因此我无法实现ExternalError
。
现在,我实现SomeTrait
:
fn do_my_things() -> Result<(), MyError> {
Ok(())
}
struct MyStruct;
impl SomeTrait for MyStruct {
fn do_stuff(&self) -> Result<i32, ExternalError> {
do_my_things()?;
Ok(200)
}
}
Full code in the playground。但是,它将无法编译:
error[E0277]: `?` couldn't convert the error to `external_module::ExternalError`
--> src/main.rs:28:23
|
28 | do_my_things()?;
| ^ the trait `std::convert::From<MyError>` is not implemented for `external_module::ExternalError`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= note: required by `std::convert::From::from`
要使其编译,我可以显式使用into()
:
do_my_things().map_err(|e| e.into())?;
Playground。这里有两个问题:
From
而不是Into
?后者似乎更合理,因为它会更宽松:From<A> for B
暗示Into<B> for A
,但并非相反。.map_err(|e| e.into())
看起来很冗长(有时我什至不得不在闭包中明确指定类型,因为编译器无法推断出它们!)某些情况:遇到这种情况时,我正在玩tonic。该库从.proto
个文件生成特征,然后希望您实现它们(请参见the basic helloworld)。如果发生故障,您需要返回Err(tonic::Status)
,它基本上包含GRPC错误代码和错误消息。我不希望我的内部错误类型与GRPC错误代码有任何关系,我只想在我的错误转换为tonic::Status
时添加它们。
答案 0 :(得分:3)
cursor
|
V
0 1 2 3
A B C
宏为initally implemented,没有隐式错误转换。该宏是从renamed到is_ok!
的,后来错误转换为implemented时,他们选择使用try!
特性,later被{在更普遍的转化特征之后的{1}}特征是在六个月后implemented。
如@mcarton所述,the RFC for the ?
operator使用FromError
特征进行错误转换。它还说:“ 后缀From<E>
运算符可以应用于Into
值,并且等效于当前的?
宏。”但是,如{ {3}},stbuehler撰写:
遗憾的是会有回归的。如果没有实现错误类型的(非平凡的)
Result
实例,则编译器可以在某些情况下推论该类型,而在使用try!()
({{1}的集合时)则无法推论该类型。 }实例受当前板条箱限制,编译板条箱时无法知道完整的Into实例集。
所以我对此的解释是,From<...>
宏在Into
和From
特征存在之前添加了错误转换支持,并且因为try!
运算符应具有相同的行为作为From
宏,并且更改为Into
会破坏类型推导,因此?
运算符是使用try!
实现的。
话虽如此,只要Into
是板条箱中的一种类型,就可以实现?
:
From