Skip to main content

Welp

Struct Welp 

Source
pub struct Welp(/* private fields */);
Expand description

A string-shaped error type for prototypes, one-off errors, and quick string contexts.

The typed-selector flow generated by #[oopsie] is the project’s primary error-handling story. Welp covers the cases where a structured variant would be overkill: prototyping, exactly-once failure modes, and adding a plain-string context to a foreign error.

use oopsie_core::{Welp, WelpResultExt as _};

fn read_config(path: &str) -> Result<String, Welp> {
    std::fs::read_to_string(path).welp_context("could not read config")
}

§Construction

  • Welp::new — fresh string error, captures a backtrace (and a span-trace when the tracing feature is enabled).
  • Welp::wrap — wrap an existing error with a string message.
  • Welp::wrap_boxed — same, for an already-boxed dyn Error.
  • Welp::from_error — wrap an existing error with no message; its Display delegates to the source.

§Adding context to a Result / Option

Bring WelpResultExt / WelpOptionExt into scope (or import from oopsie::prelude) and use welp_context / with_welp_context.

Use welp for the message-free conversion — the ?-style escape hatch anyhow/eyre give you for free. result.welp()? turns any foreign Error into a Welp without inventing a string; result.welp_context("…")? is for when a message genuinely adds information the source doesn’t already carry. Together they make fn main() -> Report<Welp> (with Welp from the prelude) the catch-all top-level error story.

§Layout

Welp is a small enum. Every variant carries a boxed (Backtrace, _) captured at construction (the second slot is the span-trace under the tracing feature and is otherwise empty) and an inline &'static Location of the call site. Traced adds a Box<str> message; Sourced adds an optional Box<str> message and the wrapped Box<dyn Error>. The message-free form (from_error / welp) is a Sourced with no message, whose Display delegates to the source.

A Sourced Welp’s Diagnostic accessors prefer the source’s traces (reached via the Provider API under the unstable-error-generic-member-access feature) and fall back to the wrap-site ones.

Implementations§

Source§

impl Welp

Source

pub fn new(message: impl Into<String>) -> Self

Build a fresh Welp from a string message. Captures a backtrace (and a span-trace when the tracing feature is enabled) at the call site.

use oopsie_core::Welp;

let err = Welp::new(format!("port {} out of range", 70_000));
assert_eq!(err.to_string(), "port 70000 out of range");
Source

pub fn wrap<E>(source: E, message: impl Into<String>) -> Self
where E: StdError + Send + Sync + 'static,

Wrap an existing error with a string message. Captures a backtrace (and a span-trace when the tracing feature is enabled) at the wrap site; when the source provides its own captured traces (via the Provider API under the unstable-error-generic-member-access feature) the Diagnostic accessors surface those instead, so the origin-most captured trace wins.

use oopsie_core::Welp;

let io_err = std::io::Error::other("disk full");
let err = Welp::wrap(io_err, "could not write");
assert_eq!(err.to_string(), "could not write");
assert!(std::error::Error::source(&err).is_some());
Source

pub fn wrap_boxed( source: Box<dyn StdError + Send + Sync + 'static>, message: impl Into<String>, ) -> Self

Wrap an already-boxed trait-object error with a string message.

Use this when the source comes from an API returning Box<dyn Error + Send + Sync + 'static> — that type is ?Sized and can’t satisfy wrap’s Sized bound, but it’s exactly the shape Welp stores internally, so no rewrapping is needed.

use oopsie_core::Welp;

let boxed: Box<dyn std::error::Error + Send + Sync + 'static> =
    Box::new(std::io::Error::other("disk full"));
let err = Welp::wrap_boxed(boxed, "could not write");
assert_eq!(err.to_string(), "could not write");
assert!(std::error::Error::source(&err).is_some());
Source

pub fn from_error<E>(source: E) -> Self
where E: StdError + Send + Sync + 'static,

Wrap an existing error with no user message: this Welp’s Display delegates to the source’s, and the source stays reachable through Error::source. Use it for the message-free ?-style conversion of a foreign error; reach for wrap when a string context adds information.

Captures a backtrace (and a span-trace under the tracing feature) at the call site; like wrap, the Diagnostic accessors surface the source’s captured traces (via the Provider API under the unstable-error-generic-member-access feature) when it has them, so the origin-most trace wins.

use oopsie_core::Welp;

let err = Welp::from_error(std::io::Error::other("disk full"));
assert_eq!(err.to_string(), "disk full");
assert!(std::error::Error::source(&err).is_some());
Source

pub fn message(&self) -> Option<&str>

The user message attached to this error, or None when it carries none (a Welp from from_error / welp delegates its Display to the wrapped source instead of owning a message).

Source

pub fn downcast_ref<E: StdError + 'static>(&self) -> Option<&E>

Borrow the wrapped source as &E when it is exactly that type.

Inspects the direct source only, not the whole chain. A Welp with no source (new / welp_context on an Option) returns None. To search the whole chain, compose with chain:

use oopsie_core::{ErrorChainExt as _, Welp};
use std::error::Error as _;

let inner = std::io::Error::other("disk full");
let err = Welp::wrap(Welp::wrap(inner, "mid"), "outer");

// The direct source is the middle `Welp`, not the io::Error.
assert!(err.downcast_ref::<std::io::Error>().is_none());

// Reach the buried io::Error by walking the chain.
let io = err
    .chain()
    .find_map(|e| e.downcast_ref::<std::io::Error>())
    .expect("io::Error is somewhere in the chain");
assert_eq!(io.to_string(), "disk full");
Source

pub fn downcast_mut<E: StdError + 'static>(&mut self) -> Option<&mut E>

Mutably borrow the wrapped source as &mut E when it is exactly that type. Like downcast_ref, inspects the direct source only.

Source

pub fn downcast<E: StdError + 'static>(self) -> Result<E, Self>

Consume this Welp and recover the wrapped source as E when it is exactly that type, returning the Welp unchanged otherwise.

Targets the direct source only. A message-free Welp is the source’s transparent wrapper, so this recovers the original foreign error:

use oopsie_core::{Welp, WelpResultExt as _};

let r: Result<(), std::io::Error> = Err(std::io::Error::other("disk full"));
let welp = r.welp().unwrap_err();
let io: std::io::Error = welp.downcast().expect("source is an io::Error");
assert_eq!(io.to_string(), "disk full");
§Errors

Returns Err(self) — message, location, and captured traces intact — when there is no source or it is not of type E.

Trait Implementations§

Source§

impl Debug for Welp

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Diagnostic for Welp

Source§

fn oopsie_backtrace(&self) -> Option<&Backtrace>

Returns the backtrace captured when this error was created.
Source§

fn oopsie_spantrace(&self) -> Option<&SpanTrace>

Returns the span trace captured when this error was created.
Source§

fn oopsie_location(&self) -> Option<&'static Location<'static>>

Returns the caller location captured when this error was created.
Source§

fn oopsie_exit_code(&self) -> Option<NonZeroU8>

Returns the process exit code this error should terminate with. Read more
Source§

fn oopsie_error_code(&self) -> Option<ErrorCode>

Returns the error code associated with this error.
Source§

fn oopsie_help_text(&self) -> Option<HelpText>

Returns the help text associated with this error.
Source§

impl Display for Welp

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for Welp

Source§

fn source(&self) -> Option<&(dyn StdError + 'static)>

Returns the lower-level source of this error, if any. Read more
Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Auto Trait Implementations§

§

impl !RefUnwindSafe for Welp

§

impl !UnwindSafe for Welp

§

impl Freeze for Welp

§

impl Send for Welp

§

impl Sync for Welp

§

impl Unpin for Welp

§

impl UnsafeUnpin for Welp

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsErrorSource for T
where T: Error + 'static,

Source§

fn as_error_source(&self) -> &(dyn Error + 'static)

Borrow this value as a &(dyn Error + 'static).
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> DropFlavorWrapper<T> for T

Source§

type Flavor = MayDrop

The DropFlavor that wraps T into Self
Source§

impl<E> ErrorChainExt for E
where E: Error + 'static,

Source§

fn chain(&self) -> Chain<'_>

Iterate this error followed by its transitive source causes. Read more
Source§

fn root_cause(&self) -> &(dyn Error + 'static)

The last error in the chain: the deepest source, or this error itself when it has none.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<E> InstrumentError for E
where TracedError<E>: From<E>,

Source§

type Instrumented = TracedError<E>

The type of the wrapped error after instrumentation
Source§

fn in_current_span(self) -> <E as InstrumentError>::Instrumented

Instrument an Error by bundling it with a SpanTrace Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more