-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider providing a bail!() macro #192
Comments
Does SNAFU vs. Failure / "Strings as errors" cover this topic? It's unclear exactly how such a macro would work with SNAFU, and what kind of overlap it would have with |
Yes, I think the common usage of
At a basic level, it could be seen as a special case for With a bit more space to roam, I think (but I haven't experimented enough yet) that there are two common UX cases that could be covered by some macro:
To be honest, I'm not advocating to add this to the library as it isn't a fundamental issue IMHO. |
Is this much better than the current return ContextSelector {/* ... */}.fail();
// bail!(ContextSelector {/* ... */});
One solution I could see would be something like: #[derive(Debug, Snafu)]
#[snafu(create_other_error(SomeName))]
enum Error {
// Optionally other variants
} This would expand to enum Error {
SomeName(String),
}
impl HasOtherError for Error {
fn construct(s: String) -> Self {
Error::SomeName(s)
}
} And the core library has trait HasOtherError {
// ...
}
// Some implementation of the macro that allows
fn foo() -> Result<(), Error> {
bail!("wow {}", 42);
} One big "problem" with this is that the current #[derive(Debug)]
#[Snafu]
#[snafu(create_other_error(SomeName))]
enum Error { /* ... */ } Switching to a procedural macro is something I've toyed around with (couldn't do before due to supporting older Rust versions) as using |
More spitballing: enum Error {
#[snafu(other)]
Other { message: String }
}
bail!("oh noes {}", 42); becomes enum Error {
Other { message: String }
}
impl snafu::FromString for Error {
fn from_string(message: String) -> Self {
Error::Other { message: String }
}
}
return Err(snafu::FromString::from_string(format!("oh noes {}", 42))).map_err(Into::into);
|
OK, I'm working towards something. Here's an example of what it looks like now: use snafu::{whatever, ResultExt};
type Result<T, E = snafu::Whatever> = std::result::Result<T, E>;
fn subtract_numbers(a: u32, b: u32) -> Result<u32> {
if a > b {
Ok(a - b)
} else {
whatever!("Can't subtract {} - {}", a, b)
}
}
fn complicated_math(a: u32, b: u32) -> Result<u32> {
let val = subtract_numbers(a, b).whatever_context("Can't do the math")?;
Ok(val * 2)
} In addition, you can add the "whatever" support to your own error types in addition to any more structured errors: #[derive(Debug, Snafu)]
enum Error {
#[snafu(whatever, display("{}", message))]
Whatever {
#[snafu(source(from(Box<dyn std::error::Error>, Some)))] // FIXME
source: Option<Box<dyn std::error::Error>>,
message: String,
backtrace: Backtrace,
},
} Would anyone be up for some beta testing / doc reading? If so, check out the branch. |
I haven't seen any previous discussion on this, so I'm opening this ticket mostly to see what is @shepmaster's stance on this.
Coming from past experiences with
error_chain
andfailure
, I got used to thebail!()
macros they both provide (with slightly different semantics) for quickly generating+returning errors:Have you maybe already considered that in the past for
snafu
? Do you have additional thoughts to share?The text was updated successfully, but these errors were encountered: