我正在遵循 这个 YouTube 指南来构建 Rust 项目。我创建了一个
error.rs
文件,在其中保存自定义错误,它看起来像这样:
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// For starter, to remove as code matures.
#[error("Generic error: {0}")]
Generic(String),
}
之后我重新导出我的
prelude.rs
中的错误
// Re-export the crate Error.
pub use crate::error::Error;
// Alias Result to be the crate Result.
pub type Result<T> = core::result::Result<T, Error>;
// Generic Wrapper tuple struct for newtype pattern,
// mostly for external type to type From/TryFrom conversions
pub struct W<T>(pub T);
并创建一个使用错误的函数:
fn foo(n: i32) -> Result<i32> {
if n == 3 {
return Error::Generic("I don'l like 3".to_string());
}
Ok(n)
}
但是当我尝试使用自定义错误时,Rust 不允许它,说我需要将其包装在
Err
值中。为什么我在返回 Result
时不能使用自己的错误,有没有办法可以避免在这种情况下包装它?
error[E0308]: mismatched types
--> src/lib.rs:12:16
|
10 | fn foo(n: i32) -> Result<i32> {
| ----------- expected `std::result::Result<i32, error::Error>` because of return type
11 | if n == 3 {
12 | return Error::Generic("I don'l like 3".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<i32, Error>`, found `Error`
|
= note: expected enum `std::result::Result<i32, error::Error>`
found enum `error::Error`
help: try wrapping the expression in `Err`
|
12 | return Err(Error::Generic("I don'l like 3".to_string()));
| ++++ +
作为澄清,YouTuber 使用以下代码解决了这个问题:
use crate::prelude::*;
use std::fs::DirEntry;
impl TryFrom<W<&DirEntry>> for String {
type Error = Error;
fn try_from(val: W<&DirEntry>) -> Result<String> {
val.0
.path()
.to_str()
.map(String::from)
.ok_or_else(|| Error::Generic(f!("Invalid path {:?}", val.0)))
}
}
因为你的返回类型是
Result
而不是Error
,所以它们是不同的类型。您必须返回其 变体 Result::Ok
或 Result::Err
之一。
ok_or_else
:
pub fn ok_or_else<E, F>(self, err: F) -> Result<T, E> where F: FnOnce() -> E, { match self { Some(v) => Ok(v), None => Err(err()), } }
如您所见,它采用一个返回错误类型
E
的闭包,而不是 Result
。它将返回值包装在 Err
中,因此使用它的代码不必包装它。