How do I generify the error of a Rust Result<T, E> to Result<T, Box<dyn std::error::Error>>?
How do I generify the error of a Rust Result<T, E> to Result<T, Box<dyn std::error::Error>>?
我正在尝试生成由 reqwest::blocking::get
函数返回的 Result
。它returns一个Result<reqwest::blocking::Response, reqwest::Error>
但是它在returns一个Result<reqwest::blocking::Response, Box<dyn std::error::Error>
.
中调用的函数
- 为什么我第一次尝试编译失败?
- 进行此转换最惯用的方法是什么?
这是第一次尝试:
fn get_example_fails() -> Result<Response, Box<dyn Error>> {
let result = blocking::get("http://example.com");
result.map_err(|error| Box::new(error))
}
它有以下错误,我不知道如何修复,但觉得通过一些小的调整可能更符合习惯 - 但我不确定要调整什么:
error[E0308]: mismatched types
--> src/bittrex.rs:143:9
|
141 | fn get_example_fails() -> Result<Response, Box<dyn Error>> {
| -------------------------------- expected `Result<reqwes
t::blocking::Response, Box<(dyn StdError + 'static)>>` because of return type
142 | let result = blocking::get("http://example.com");
143 | result.map_err(|error| Box::new(error))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn StdError`,
found struct `reqwest::Error`
|
= note: expected enum `Result<_, Box<(dyn StdError + 'static)>>`
found enum `Result<_, Box<reqwest::Error>>`
此尝试编译但似乎冗长:
fn get_example_works() -> Result<Response, Box<dyn Error>> {
let result = blocking::get("http://example.com");
match result {
Ok(resp) => Ok(resp),
Err(error) => Err(Box::new(error)),
}
}
这是因为编译器在这里过于热心了。请注意 Box::new(error)
只是将 error
放入 Box
中,因此您会得到一个强类型的 Box<reqwest:Error>
,正如编译器报告的那样。但是你想要的是 dyn Error
的特征对象,Box<reqwest:Error>
可能是,但编译器不会做出这种类型弱化假设。修复是手动明确的:
fn get_example_fails() -> Result<Response, Box<dyn Error>> {
let result = blocking::get("http://example.com");
result.map_err(|error| Box::new(error) as Box<dyn Error>)
}
注意额外的 as Box<dyn Error>
,它向编译器表明该值应该向下转换,并且它是 Box
中的具体 reqwest::Error
的事实应该被删除。
第二个示例编译良好的原因是类型推断。在第一个示例中,从函数中编辑的 return 类型将是从 .map_err()
中编辑的类型 return,即 Result<Response, Box<reqwest::Error>>
- 就是这样。类型不匹配,所以你得到一个错误。在第二个例子中,match
构造了一个全新的 Result
并且 Rust 必须为此推断出 T
和 E
;所以类型推断开始了。在第二种情况下,由于函数的 return 值的推断相对于 Box<dyn Error>
是成功的。但是对于 map_err()
,类型推断不能“调查”map_err()
-body 并弱化 它是 return 类型;已经太晚了,类型是固定的。这就是为什么您必须按照上面的建议手动执行此操作的原因。
我正在尝试生成由 reqwest::blocking::get
函数返回的 Result
。它returns一个Result<reqwest::blocking::Response, reqwest::Error>
但是它在returns一个Result<reqwest::blocking::Response, Box<dyn std::error::Error>
.
- 为什么我第一次尝试编译失败?
- 进行此转换最惯用的方法是什么?
这是第一次尝试:
fn get_example_fails() -> Result<Response, Box<dyn Error>> {
let result = blocking::get("http://example.com");
result.map_err(|error| Box::new(error))
}
它有以下错误,我不知道如何修复,但觉得通过一些小的调整可能更符合习惯 - 但我不确定要调整什么:
error[E0308]: mismatched types
--> src/bittrex.rs:143:9
|
141 | fn get_example_fails() -> Result<Response, Box<dyn Error>> {
| -------------------------------- expected `Result<reqwes
t::blocking::Response, Box<(dyn StdError + 'static)>>` because of return type
142 | let result = blocking::get("http://example.com");
143 | result.map_err(|error| Box::new(error))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn StdError`,
found struct `reqwest::Error`
|
= note: expected enum `Result<_, Box<(dyn StdError + 'static)>>`
found enum `Result<_, Box<reqwest::Error>>`
此尝试编译但似乎冗长:
fn get_example_works() -> Result<Response, Box<dyn Error>> {
let result = blocking::get("http://example.com");
match result {
Ok(resp) => Ok(resp),
Err(error) => Err(Box::new(error)),
}
}
这是因为编译器在这里过于热心了。请注意 Box::new(error)
只是将 error
放入 Box
中,因此您会得到一个强类型的 Box<reqwest:Error>
,正如编译器报告的那样。但是你想要的是 dyn Error
的特征对象,Box<reqwest:Error>
可能是,但编译器不会做出这种类型弱化假设。修复是手动明确的:
fn get_example_fails() -> Result<Response, Box<dyn Error>> {
let result = blocking::get("http://example.com");
result.map_err(|error| Box::new(error) as Box<dyn Error>)
}
注意额外的 as Box<dyn Error>
,它向编译器表明该值应该向下转换,并且它是 Box
中的具体 reqwest::Error
的事实应该被删除。
第二个示例编译良好的原因是类型推断。在第一个示例中,从函数中编辑的 return 类型将是从 .map_err()
中编辑的类型 return,即 Result<Response, Box<reqwest::Error>>
- 就是这样。类型不匹配,所以你得到一个错误。在第二个例子中,match
构造了一个全新的 Result
并且 Rust 必须为此推断出 T
和 E
;所以类型推断开始了。在第二种情况下,由于函数的 return 值的推断相对于 Box<dyn Error>
是成功的。但是对于 map_err()
,类型推断不能“调查”map_err()
-body 并弱化 它是 return 类型;已经太晚了,类型是固定的。这就是为什么您必须按照上面的建议手动执行此操作的原因。