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>
fn context<C>(self, context: C) -> Result<T, Error>
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>
fn with_context<C, F>(self, f: F) -> Result<T, Error>
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.