Context

Trait Context 

pub trait Context<T, E>: Sealed {
    // Required methods
    fn context<C>(self, context: C) -> Result<T, Error>
       where C: Display + Send + Sync + 'static;
    fn with_context<C, F>(self, f: F) -> Result<T, Error>
       where C: Display + Send + Sync + 'static,
             F: FnOnce() -> C;
}
Expand description

Extension trait to add error context to results.

This extension trait, and its methods, are the primary way to create error chains. An error’s debug output will include the full chain of errors. Errors in these chains are accessible via the Error::chain and Error::root_cause methods.

After applying error context of type C, calling error.is::<C>() will return true for the new error (unless there was a memory allocation failure) in addition to any other types T for which it was already the case that error.is::<T>().

This boxes the inner C type, but if that box allocation fails, then this trait’s functions return an Error where error.is::<OutOfMemory>() is true.

§Example

use wasmtime::{Context as _, Result};

fn u32_to_u8(x: u32) -> Result<u8> {
    let y = u8::try_from(x).with_context(|| {
        format!("failed to convert `{x}` into a `u8` (max = `{}`)", u8::MAX)
    })?;
    Ok(y)
}

let x = u32_to_u8(42).unwrap();
assert_eq!(x, 42);

let error = u32_to_u8(999).unwrap_err();

// The error is a `String` because of our added context.
assert!(error.is::<String>());
assert_eq!(
    error.to_string(),
    "failed to convert `999` into a `u8` (max = `255`)",
);

// But it is also a `TryFromIntError` because of the inner error.
assert!(error.is::<std::num::TryFromIntError>());
assert_eq!(
    error.root_cause().to_string(),
    "out of range integral type conversion attempted",
);

// The debug output of the error contains the full error chain.
assert_eq!(
    format!("{error:?}").trim(),
    r#"
failed to convert `999` into a `u8` (max = `255`)

Caused by:
    out of range integral type conversion attempted
    "#.trim(),
);

§Example with Option<T>

You can also use this trait to create the initial, root-cause Error when a fallible function returns an Option:

use wasmtime::{Context as _, Result};

fn try_get<T>(slice: &[T], i: usize) -> Result<&T> {
    let elem: Option<&T> = slice.get(i);
    elem.with_context(|| {
        format!("out of bounds access: index is {i} but length is {}", slice.len())
    })
}

let arr = [921, 36, 123, 42, 785];

let x = try_get(&arr, 2).unwrap();
assert_eq!(*x, 123);

let error = try_get(&arr, 9999).unwrap_err();
assert_eq!(
    error.to_string(),
    "out of bounds access: index is 9999 but length is 5",
);

Required Methods§

fn context<C>(self, context: C) -> Result<T, Error>
where C: Display + Send + Sync + 'static,

Add additional, already-computed error context to this result.

Because this method requires that the error context is already computed, it should only be used when the context is already available or is effectively a constant. Otherwise, it effectively forces computation of the context, even when we aren’t on an error path. The Context::with_context method is preferred in these scenarios, as it lazily computes the error context, only doing so when we are actually on an error path.

fn with_context<C, F>(self, f: F) -> Result<T, Error>
where C: Display + Send + Sync + 'static, F: FnOnce() -> C,

Add additional, lazily-computed error context to this result.

Only invokes f to compute the error context when we are actually on an error path. Does not invoke f if we are not on an error path.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

§

impl<T> Context<T, Infallible> for Option<T>

§

impl<T> Context<T, Error> for Result<T, Error>

§

impl<T, E> Context<T, E> for Result<T, E>
where E: Error + Send + Sync + 'static,