rust-lang-deprecated / error-chain

Error boilerplate for Rust
Apache License 2.0
729 stars 111 forks source link

Matching on causes? #206

Open bennofs opened 7 years ago

bennofs commented 7 years ago

I currently have error chain setup like this:

/// main.rs
use db;

error_chain! {
  errors {
    DbRead {
// ...
    }
  }
}
/// db.rs
error_chain! {
  // ...
  foreign_links {
    Io(io::Error);
  }
}

How do I implement this:

I want to give a special error message / return different exit code / handle differently when there is a DbRead error where the cause is the IO error file not found.

Yamakaky commented 7 years ago

For now, I don't think you can. You would need a Any bound on the cause, I think.

bennofs commented 7 years ago

@Yamakaky any suggestions on how to deal with this case? Do I need to use a "flat" error hierarchy?

Yamakaky commented 7 years ago

Silly me, you can. See file:///home/yamakaky/dev/rust/error-chain/target/doc/error_chain/example_generated/enum.ErrorKind.html, Inner variant. For your own code, try cargo doc to see the hierarchy

Cobrand commented 7 years ago

The real link (for those who don't have access to Yamakaky's computer)

Yamakaky commented 7 years ago

ahahahahah

bennofs commented 7 years ago

@Yamakaky That would only work if I used links I believe.

Yamakaky commented 7 years ago

Yes. Can't you do this?

debris commented 7 years ago

I have the same issue:

error_chain! {
    foreign_links {
        Io(io::Error);
    }
}

fn load<P: AsRef<Path>>(path: P) -> Result<Database, Error> {
    let mut file = fs::File::open(path).chain_err(|| "Cannot open database")?;
    // logic...
}

fn main() {
    match load("file.txt") {
        // I would like to match io::ErrorKind::NotFound  here, but it's not possible to get internal error
    }
}
bennofs commented 7 years ago

@Yamakaky the problem with using links is that I won't get nice hierarchical error messages for the remaining, non special causes. For example, I wouldn't be able to get:

Error: database read failed
Cause: more specific error message

@debris I think that is a different issue. If I am not mistaken, foreign_links creates a new error kind variant with the foreign error attached. Can you match on that?

pronebird commented 7 years ago

@bennofs so how does one match against foreign_links? I tried to iterate over errors but then I can't match.

bennofs commented 7 years ago

@pronebird like this:

#[macro_use] extern crate error_chain;

use std::io;
error_chain! {
      foreign_links {
            Io(io::Error);
      }
}

fn test() -> Result<()> {
    let mut line = String::new();
    io::stdin().read_line(&mut line)?;
    Ok(())
}

fn main() {
    if let Err(e) = test() {
        match *e.kind() {
            ErrorKind::Io(ref e) => {
                let x: &io::Error = e;
               //... 
            },
            _ => {}
        }
    }
}