Skip to main content

Location

Type Alias Location 

Source
pub type Location = &'static Location<'static>;
Expand description

The source code location where the error was reported.

To use it, add a field of type Location to your error and register it as implicitly generated data. When constructing the error, you do not need to provide the location:

#[derive(Debug, Snafu)]
struct NeighborhoodError {
    #[snafu(implicit)]
    loc: snafu::Location,
}

fn check_next_door() -> Result<(), NeighborhoodError> {
    ensure!(everything_quiet(), NeighborhoodSnafu);
    Ok(())
}

§Limitations

Implicitly generated data, including Location, is generated when the wrapping error value is constructed:

// The first we know about the error is on this line:
let e = fallible_code();
// but the location will correspond to this line:
e.context(InterestingSnafu)?;

If you have disabled the context selector, the Location will correspond to where the From implementation is invoked. This is usually part of the ? operator:

// The first we know about the error is on this line:
let e = fallible_code();
// but the location will correspond to this line:
e?;

Inspecting the code at the generated Location will usually quickly lead back to the original error, but it’s recommended to create the wrapping error as close to the original error location to reduce confusion.

§Asynchronous code

When using SNAFU’s TryFutureExt or TryStreamExt extension traits, the automatically captured location will correspond to where the future or stream was polled, not where it was created. Additionally, many Future or Stream combinators do not forward the caller’s location to their closures, causing the recorded location to be inside of the future combinator’s library.

There are two workarounds:

  1. Avoid combinators and use the non-async ResultExt
  2. Construct the location explicitly, such as by the location! macro
// Non-ideal: will report where `wrapped_error_future` is `.await`ed.
let wrapped_error_future = error_future.context(ImplicitLocationSnafu);

// Better: will report the location of `.context`.
let wrapped_error_future = async { error_future.await.context(ImplicitLocationSnafu) };

// Better: Will report the location of `location!`
let wrapped_error_future = error_future.with_context(|_| ExplicitLocationSnafu {
    location: location!(),
});

#[derive(Debug, Snafu)]
struct ImplicitLocationError {
    source: AnotherError,
    #[snafu(implicit)]
    location: snafu::Location,
}

#[derive(Debug, Snafu)]
struct ExplicitLocationError {
    source: AnotherError,
    location: snafu::Location,
}

Trait Implementations§

Source§

impl GenerateImplicitData for Location

Source§

fn generate() -> Self

Build the data.
Source§

fn generate_with_source(source: &dyn Error) -> Self
where Self: Sized,

Build the data using the given source