Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does Rust compiler won't let me use custom error type in Result

I’m following this YouTube guide on structuring a Rust project. I created an error.rs file where I keep my custom errors and it looks like this:

#[derive(thiserror::Error, Debug)]
pub enum Error {
    /// For starter, to remove as code matures.
    #[error("Generic error: {0}")]
    Generic(String),

}

After that I re-export the error in my 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);

And create a function that would use the error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

fn foo(n: i32) -> Result<i32> {
    if n == 3 {
        return Error::Generic("I don'l like 3".to_string());
    }
    Ok(n)
}

But when I try to use my custom error, Rust won’t allow it, saying that I need to wrap it in an Err value. Why can’t I use my own error when returning the Result, and is there a way I can avoid wrapping it in this situation?

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()));
   |                ++++                                            +

Just as a clarification, the youtuber got around this with the following code:

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)))
    }
}

>Solution :

Because your return type is Result not Error, they are different types. You have to return one of it’s variants Result::Ok or 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()),
    }
}

as you can see takes a closure that returns the error type E, not a Result. And it wraps the returned value in Err, so code using it doesn’t have to wrap it.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading