# error-path-macros
`error-path-macros` provides procedural attribute macros that automatically add an operational address segment when an error leaves a `Result`-returning Rust function or impl method. An address is a stable identifier for where an error belongs in a system, not a stack trace that reconstructs how it was reached.
```text
login.api.request_login
```
Most applications should not depend on this crate directly. The [`error-path`](https://crates.io/crates/error-path) crate re-exports these macros through its `macros` feature and also supplies the required `WithErrorPath` trait and optional adapters.
## Recommended installation
```toml
[dependencies]
error-path = { version = "0.1", features = ["macros"] }
```
## Direct installation
For an advanced setup, such as re-exporting these macros from another crate, depend on this crate together with the core crate:
```toml
[dependencies]
error-path = "0.1"
error-path-macros = "0.1"
```
Generated code refers to `::error_path::WithErrorPath`. The core crate is therefore required; if you rename that dependency, re-export it under the `error_path` name. The minimum supported Rust version is 1.77.
## `#[error_path]`
Attach one address segment to a single `Result`-returning function. Without an argument, the macro uses the function name; with a string argument, it uses that string. Path strings are parsed with `error-path`'s current global delimiter.
```rust
use error_path::{ErrorPath, WithErrorPath};
use error_path_macros::error_path;
#[derive(Debug)]
struct ProfileError { path: ErrorPath }
impl WithErrorPath for ProfileError {
fn with_error_path(mut self, path: &'static str) -> Self {
self.path.prepend_path(path);
self
}
}
#[error_path]
fn load_profile() -> Result<(), ProfileError> {
Err(ProfileError { path: ErrorPath::new() })
}
#[error_path("login.api")]
fn request_login() -> Result<(), ProfileError> {
load_profile()
}
```
Conceptually, the macro runs the original body and adds this operation to its result:
```rust
result.map_err(|error| error_path::WithErrorPath::with_error_path(error, "login.api"))
```
Both synchronous and `async` functions are supported, while the original visibility and signature are preserved.
## `#[error_path_impl]`
Wrap result-returning methods in an `impl` block with a `{base}.{method_name}` address.
```rust
use error_path::{ErrorPath, WithErrorPath};
use error_path_macros::{error_path_impl, error_path_skip};
struct LoginApi;
#[error_path_impl("login.api")]
impl LoginApi {
fn request_login(&self) -> Result<(), ProfileError> {
Err(ProfileError { path: ErrorPath::new() })
}
#[error_path_skip]
fn health_check(&self) -> Result<(), ProfileError> {
Ok(())
}
}
```
Without an argument, the base is inferred as follows:
- trait implementation: trait name
- inherent implementation: type name
For example, `#[error_path_impl]` on `impl LoginApi for LoginApiImpl` produces `LoginApi.request_login`. Supply `#[error_path_impl("login.api")]` when you want a stable alias instead.
## `#[error_path_skip]`
Use `#[error_path_skip]` for a method inside an `#[error_path_impl]` block that should be left unchanged. The enclosing `#[error_path_impl]` consumes this marker; it does not add a path when used alone.
## Error type compatibility
The macros know no concrete error type. They call only `WithErrorPath`, so they work with `Result<T, E>` when `E: WithErrorPath`.
The core `error-path` crate provides `ErrorPath` and optional adapters for `anyhow`, `eyre`, `error-stack`, and `stacked_errors`. Custom error types, including types produced by `thiserror`, work by implementing `WithErrorPath`.
## Limitations
- Apply `#[error_path]` only to a function returning `Result`. On another return type, generated code calls `map_err` and will not compile.
- `#[error_path_impl]` automatically wraps only methods whose final return-type name ends in `Result`.
- Panics, threads, and errors inside spawned tasks are not captured automatically. A segment is added only when a `Result` error crosses the current function boundary.
- Addresses are not inferred from source file paths or runtime stack traces. Supply a stable string or use the function, trait, and type name defaults.
- The macros use `::error_path`; dependency renaming requires the re-export arrangement described above.
## Related documentation
- [error-path core crate](https://crates.io/crates/error-path)
- [Project documentation and examples](https://github.com/yongaru/error-path-kit)
- [API documentation](https://docs.rs/error-path-macros)
- [Changelog](https://github.com/yongaru/error-path-kit/blob/main/CHANGELOG.md)
## License
Licensed under either Apache-2.0 or MIT, at your option.
## Author
Created and maintained by 용사장. [akira76@gmail.com](mailto:akira76@gmail.com)