pub trait AtTraceable: Sized {
Show 21 methods
// Required methods
fn trace_mut(&mut self) -> &mut AtTrace;
fn trace(&self) -> Option<&AtTrace>;
fn fmt_message(&self, f: &mut Formatter<'_>) -> Result;
// Provided methods
fn at(self) -> Self { ... }
fn at_str(self, msg: &'static str) -> Self { ... }
fn at_string(self, f: impl FnOnce() -> String) -> Self { ... }
fn at_data<T: Display + Send + Sync + 'static>(
self,
f: impl FnOnce() -> T,
) -> Self { ... }
fn at_debug<T: Debug + Send + Sync + 'static>(
self,
f: impl FnOnce() -> T,
) -> Self { ... }
fn at_error<E: Error + Send + Sync + 'static>(self, err: E) -> Self { ... }
fn at_crate(self, info: &'static AtCrateInfo) -> Self { ... }
fn at_fn<F: Fn()>(self, _marker: F) -> Self { ... }
fn at_named(self, name: &'static str) -> Self { ... }
fn at_pop(&mut self) -> Option<AtFrameOwned> { ... }
fn at_push(&mut self, segment: AtFrameOwned) { ... }
fn at_first_pop(&mut self) -> Option<AtFrameOwned> { ... }
fn at_first_insert(&mut self, segment: AtFrameOwned) { ... }
fn map_traceable<E2, F>(self, f: F) -> E2
where F: FnOnce(Self) -> E2,
E2: AtTraceable { ... }
fn into_at<E2, F>(self, f: F) -> At<E2>
where F: FnOnce(Self) -> E2 { ... }
fn full_trace(&self) -> impl Display + '_ { ... }
fn last_error_trace(&self) -> impl Display + '_ { ... }
fn last_error(&self) -> impl Display + '_ { ... }
}Expand description
Trait for types that embed an AtTrace directly.
Implement this trait to get all the .at_*() methods on your custom error types.
Three methods are required:
trace_mut()- mutable access to tracetrace()- immutable access to tracefmt_message()- format the error message
§Example: Inline trace
use whereat::{AtTrace, AtTraceable};
use std::fmt;
struct MyError {
kind: &'static str,
trace: AtTrace,
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace { &mut self.trace }
fn trace(&self) -> Option<&AtTrace> { Some(&self.trace) }
fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)
}
}
impl MyError {
#[track_caller]
fn new(kind: &'static str) -> Self {
Self { kind, trace: AtTrace::capture() }
}
}
// Now you can chain .at_*() methods
let err = MyError::new("not_found").at_str("looking up user");§Example: Boxed trace (smaller error type)
use whereat::{AtTrace, AtTraceable};
use std::fmt;
struct MyError {
kind: &'static str,
trace: Box<AtTrace>, // 8 bytes instead of sizeof(AtTrace)
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace { &mut self.trace }
fn trace(&self) -> Option<&AtTrace> { Some(&self.trace) }
fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)
}
}
impl MyError {
#[track_caller]
fn new(kind: &'static str) -> Self {
Self { kind, trace: Box::new(AtTrace::capture()) }
}
}§Example: Optional boxed trace (lazy allocation)
use whereat::{AtTrace, AtTraceable};
use std::fmt;
struct MyError {
kind: &'static str,
trace: Option<Box<AtTrace>>, // None until first .at_*() call
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace {
self.trace.get_or_insert_with(|| Box::new(AtTrace::new()))
}
fn trace(&self) -> Option<&AtTrace> { self.trace.as_deref() }
fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)
}
}
impl MyError {
fn new(kind: &'static str) -> Self { // No #[track_caller] needed
Self { kind, trace: None }
}
}
// Trace allocated lazily on first .at_*() call
let err = MyError::new("not_found").at_str("context");§Why use this over At<E>?
Use AtTraceable when you want:
- Full control over your error type’s layout
- Custom storage strategy (inline, boxed, or optional)
- To define your own error constructors
Use At<E> when you want:
- Minimal changes to existing code
- To wrap errors from external crates
- The simplest possible setup
Required Methods§
Sourcefn trace(&self) -> Option<&AtTrace>
fn trace(&self) -> Option<&AtTrace>
Get an immutable reference to the trace, if allocated.
Returns None if no trace has been allocated yet (for lazy storage patterns).
For inline storage, this always returns Some.
Sourcefn fmt_message(&self, f: &mut Formatter<'_>) -> Result
fn fmt_message(&self, f: &mut Formatter<'_>) -> Result
Format just the error message (without trace).
This is used by the trace formatters to show the error message separately from the trace. Typically delegates to your error kind’s Display.
§Example
use whereat::{AtTrace, AtTraceable};
use std::fmt;
#[derive(Debug)]
enum ErrorKind {
NotFound,
InvalidInput(String),
}
struct MyError {
kind: ErrorKind,
trace: AtTrace,
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace { &mut self.trace }
fn trace(&self) -> Option<&AtTrace> { Some(&self.trace) }
fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
ErrorKind::NotFound => write!(f, "not found"),
ErrorKind::InvalidInput(s) => write!(f, "invalid input: {}", s),
}
}
}Provided Methods§
Sourcefn at_str(self, msg: &'static str) -> Self
fn at_str(self, msg: &'static str) -> Self
Add a static string context to the last location (or create one if empty).
Sourcefn at_string(self, f: impl FnOnce() -> String) -> Self
fn at_string(self, f: impl FnOnce() -> String) -> Self
Add a lazily-computed string context to the last location (or create one if empty).
Sourcefn at_data<T: Display + Send + Sync + 'static>(
self,
f: impl FnOnce() -> T,
) -> Self
fn at_data<T: Display + Send + Sync + 'static>( self, f: impl FnOnce() -> T, ) -> Self
Add lazily-computed typed context (Display) to the last location (or create one if empty).
Sourcefn at_debug<T: Debug + Send + Sync + 'static>(
self,
f: impl FnOnce() -> T,
) -> Self
fn at_debug<T: Debug + Send + Sync + 'static>( self, f: impl FnOnce() -> T, ) -> Self
Add lazily-computed typed context (Debug) to the last location (or create one if empty).
Sourcefn at_error<E: Error + Send + Sync + 'static>(self, err: E) -> Self
fn at_error<E: Error + Send + Sync + 'static>(self, err: E) -> Self
Add an error as context to the last location (or create one if empty).
Use this to attach a source error that implements core::error::Error.
Sourcefn at_crate(self, info: &'static AtCrateInfo) -> Self
fn at_crate(self, info: &'static AtCrateInfo) -> Self
Add a crate boundary marker to the last location (or create one if empty).
Uses inline storage if no crate_info is set yet; only allocates a context entry when crossing to a different crate.
Sourcefn at_fn<F: Fn()>(self, _marker: F) -> Self
fn at_fn<F: Fn()>(self, _marker: F) -> Self
Add a location frame with the caller’s function name as context.
Captures both file:line:col AND the function name at zero runtime cost.
Pass an empty closure || {} - its type includes the parent function name.
§Example
use whereat::{AtTrace, AtTraceable};
struct MyError {
trace: AtTrace,
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace { &mut self.trace }
fn trace(&self) -> Option<&AtTrace> { Some(&self.trace) }
fn fmt_message(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "my error")
}
}
impl MyError {
#[track_caller]
fn new() -> Self {
Self { trace: AtTrace::capture() }
}
}
fn do_something() -> Result<(), MyError> {
Err(MyError::new().at_fn(|| {})) // Captures file:line + "do_something"
}Sourcefn at_named(self, name: &'static str) -> Self
fn at_named(self, name: &'static str) -> Self
Add a location frame with an explicit name as context.
Like at_fn but with an explicit label instead of
auto-detecting the function name.
Sourcefn at_pop(&mut self) -> Option<AtFrameOwned>
fn at_pop(&mut self) -> Option<AtFrameOwned>
Pop the most recent location and its contexts from the trace.
Sourcefn at_push(&mut self, segment: AtFrameOwned)
fn at_push(&mut self, segment: AtFrameOwned)
Push a segment (location + contexts) to the end of the trace.
Sourcefn at_first_pop(&mut self) -> Option<AtFrameOwned>
fn at_first_pop(&mut self) -> Option<AtFrameOwned>
Pop the oldest location and its contexts from the trace.
Sourcefn at_first_insert(&mut self, segment: AtFrameOwned)
fn at_first_insert(&mut self, segment: AtFrameOwned)
Insert a segment (location + contexts) at the beginning of the trace.
Sourcefn map_traceable<E2, F>(self, f: F) -> E2where
F: FnOnce(Self) -> E2,
E2: AtTraceable,
fn map_traceable<E2, F>(self, f: F) -> E2where
F: FnOnce(Self) -> E2,
E2: AtTraceable,
Convert to another AtTraceable type, transferring the trace.
The trace is moved from self to the new error.
Sourcefn into_at<E2, F>(self, f: F) -> At<E2>where
F: FnOnce(Self) -> E2,
fn into_at<E2, F>(self, f: F) -> At<E2>where
F: FnOnce(Self) -> E2,
Convert to At<E2>, transferring the trace.
Sourcefn full_trace(&self) -> impl Display + '_
fn full_trace(&self) -> impl Display + '_
Format with full trace (message + all frames with contexts).
Returns a formatter that displays:
- The error message (via
fmt_message) - All trace frames with locations
- All context strings attached to each frame
- Nested error chains for error contexts
§Example
use whereat::{AtTrace, AtTraceable};
use std::fmt;
struct MyError {
msg: &'static str,
trace: AtTrace,
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace { &mut self.trace }
fn trace(&self) -> Option<&AtTrace> { Some(&self.trace) }
fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl MyError {
#[track_caller]
fn new(msg: &'static str) -> Self {
Self { msg, trace: AtTrace::capture() }
}
}
let err = MyError::new("something failed").at_str("while loading");
println!("{}", err.full_trace());
// Output:
// something failed
// at src/main.rs:10:15
// while loadingSourcefn last_error_trace(&self) -> impl Display + '_
fn last_error_trace(&self) -> impl Display + '_
Format with trace locations only (message + locations, no context strings).
Returns a formatter that displays:
- The error message (via
fmt_message) - All trace frame locations
- NO context strings (for compact output)
§Example
use whereat::{AtTrace, AtTraceable};
use std::fmt;
struct MyError {
msg: &'static str,
trace: AtTrace,
}
impl AtTraceable for MyError {
fn trace_mut(&mut self) -> &mut AtTrace { &mut self.trace }
fn trace(&self) -> Option<&AtTrace> { Some(&self.trace) }
fn fmt_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl MyError {
#[track_caller]
fn new(msg: &'static str) -> Self {
Self { msg, trace: AtTrace::capture() }
}
}
let err = MyError::new("something failed").at_str("while loading");
println!("{}", err.last_error_trace());
// Output:
// something failed
// at src/main.rs:10:15
// (note: "while loading" context is omitted)Sourcefn last_error(&self) -> impl Display + '_
fn last_error(&self) -> impl Display + '_
Format just the error message (no trace).
Returns a formatter that only displays the error message via fmt_message.
Use this when you want to show the error without any trace information.
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.