为什么 Rust 编译器不允许我在结果中使用自定义错误类型

问题描述 投票:0回答:1

我正在遵循 这个 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)))
    }
}
rust error-handling
1个回答
1
投票

因为你的返回类型是

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
中,因此使用它的代码不必包装它。

© www.soinside.com 2019 - 2024. All rights reserved.