-
Notifications
You must be signed in to change notification settings - Fork 70
Closed
Description
The documentation talks about splitting a source error into two separate errors. In my experience the converse also often happens, sometimes you want to combine several source errors into a single one. However as a newbie, I've been unable to make this happen. I've attached an MRE of one attempt, but I'm not necessarily asking for how to make my MRE compile -- something completely different that matches my use case would be awesome. For example, I use the InnerError pattern and source(false) but a less verbose solution that doesn't need one or both of those likely would be even better.
use rand::Rng;
use snafu::prelude::*;
#[derive(Debug, Snafu)]
pub enum Error {
/// Error in the construction of the NFT
#[snafu(display("Parse Error on {field}: {source}"))]
ParseError {
field: String,
#[snafu(source(false))]
source: InnerParseError,
},
}
#[derive(Debug, Snafu)]
pub enum InnerParseError {
#[snafu(display("YAMLError {source}"))]
YamlError {
#[snafu(source(false))]
source: serde_yaml::Error,
},
#[snafu(display("JSONError {source}"))]
JsonError {
#[snafu(source(false))]
source: serde_json::Error,
},
#[snafu(display("{message}"))]
MessageError { message: String },
}
fn main_wrapped() -> Result<String, Error> {
let r: i32 = rand::thread_rng().gen_range(0..3);
Ok(match r {
0 => {
let _ = serde_yaml::from_str("invalid yaml").with_context(|e| ParseSnafu {
field: "0",
source: YamlSnafu { source: e },
})?;
"0".to_string()
}
1 => {
let _ = serde_json::from_str("invalid json").with_context(|e| ParseSnafu {
field: "0",
source: JsonSnafu { source: e },
})?;
"1".to_string()
}
_ => {
ensure!(
false,
ParseSnafu {
field: "2",
source: InnerParseError::MessageError {
message: "blah".to_owned()
}
}
);
"2".to_string()
}
})
}
fn main() {
match main_wrapped() {
Ok(s) => {
panic!("#{s:?}");
}
Err(e) => {
println!("#{e:?}");
}
}
}[package]
name = "mre"
version = "0.1.0"
edition = "2021"
[dependencies]
rand = "0.8"
serde_yaml = "0.8"
serde_json = "1"
snafu = "0.7"
/home/blarsen/.cargo/bin/cargo run --manifest-path /work/gitnft/mre/Cargo.toml
Compiling mre v0.1.0 (/work/gitnft/mre)
error[E0271]: type mismatch resolving `<ParseSnafu<&str, YamlSnafu<&mut serde_yaml::Error>> as IntoError<Error>>::Source == serde_yaml::Error`
--> src/main.rs:36:58
|
36 | let _ = serde_yaml::from_str("invalid yaml").with_context(|e| ParseSnafu {
| ^^^^^^^^^^^^ expected struct `serde_yaml::Error`, found struct `NoneError`
|
note: required by a bound in `snafu::ResultExt::with_context`
--> /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/snafu-0.7.0/src/lib.rs:529:26
|
529 | C: IntoError<E2, Source = E>,
| ^^^^^^^^^^ required by this bound in `snafu::ResultExt::with_context`
error[E0277]: the trait bound `InnerParseError: From<YamlSnafu<&mut serde_yaml::Error>>` is not satisfied
--> src/main.rs:36:71
|
36 | let _ = serde_yaml::from_str("invalid yaml").with_context(|e| ParseSnafu {
| __________________________________________________________------------_^
| | |
| | required by a bound introduced by this call
37 | | field: "0",
38 | | source: YamlSnafu { source: e },
39 | | })?;
| |_____________^ the trait `From<YamlSnafu<&mut serde_yaml::Error>>` is not implemented for `InnerParseError`
|
= note: required because of the requirements on the impl of `Into<InnerParseError>` for `YamlSnafu<&mut serde_yaml::Error>`
note: required because of the requirements on the impl of `IntoError<Error>` for `ParseSnafu<&str, YamlSnafu<&mut serde_yaml::Error>>`
--> src/main.rs:4:17
|
4 | #[derive(Debug, Snafu)]
| ^^^^^
note: required by a bound in `snafu::ResultExt::with_context`
--> /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/snafu-0.7.0/src/lib.rs:529:12
|
529 | C: IntoError<E2, Source = E>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `snafu::ResultExt::with_context`
= note: this error originates in the derive macro `Snafu` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0271]: type mismatch resolving `<ParseSnafu<&str, JsonSnafu<&mut serde_json::Error>> as IntoError<Error>>::Source == serde_json::Error`
--> src/main.rs:43:58
|
43 | let _ = serde_json::from_str("invalid json").with_context(|e| ParseSnafu {
| ^^^^^^^^^^^^ expected struct `serde_json::Error`, found struct `NoneError`
|
note: required by a bound in `snafu::ResultExt::with_context`
--> /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/snafu-0.7.0/src/lib.rs:529:26
|
529 | C: IntoError<E2, Source = E>,
| ^^^^^^^^^^ required by this bound in `snafu::ResultExt::with_context`
error[E0277]: the trait bound `InnerParseError: From<JsonSnafu<&mut serde_json::Error>>` is not satisfied
--> src/main.rs:43:71
|
43 | let _ = serde_json::from_str("invalid json").with_context(|e| ParseSnafu {
| __________________________________________________________------------_^
| | |
| | required by a bound introduced by this call
44 | | field: "0",
45 | | source: JsonSnafu { source: e },
46 | | })?;
| |_____________^ the trait `From<JsonSnafu<&mut serde_json::Error>>` is not implemented for `InnerParseError`
|
= note: required because of the requirements on the impl of `Into<InnerParseError>` for `JsonSnafu<&mut serde_json::Error>`
note: required because of the requirements on the impl of `IntoError<Error>` for `ParseSnafu<&str, JsonSnafu<&mut serde_json::Error>>`
--> src/main.rs:4:17
|
4 | #[derive(Debug, Snafu)]
| ^^^^^
note: required by a bound in `snafu::ResultExt::with_context`
--> /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/snafu-0.7.0/src/lib.rs:529:12
|
529 | C: IntoError<E2, Source = E>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `snafu::ResultExt::with_context`
= note: this error originates in the derive macro `Snafu` (in Nightly builds, run with -Z macro-backtrace for more info)
Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
Metadata
Metadata
Assignees
Labels
No labels