# error-location
[](https://crates.io/crates/error-location)
[](https://docs.rs/error-location)
[](https://github.com/yourusername/error-location#license)
[](https://github.com/yourusername/error-location/actions)
A lightweight utility for capturing and displaying error locations in Rust.
This crate provides a simple wrapper around `std::panic::Location` to make it easier to track where errors originate in your code. It's particularly useful when building custom error types with crates like `thiserror`.
## Features
- **Zero dependencies**: Only uses `std`
- **Lightweight**: Minimal overhead with compile-time tracking
- **Type-safe**: Leverages Rust's `#[track_caller]` attribute
- **Display formatting**: Clean, readable output format `[file:line:column]`
## Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
error-location = "0.1"
```
## Usage
### Basic Usage
```rust
use error_location::ErrorLocation;
use std::panic::Location;
#[track_caller]
fn might_fail() -> Result<(), String> {
let location = ErrorLocation::from(Location::caller());
Err(format!("Something went wrong at {}", location))
}
fn main() {
match might_fail() {
Ok(_) => println!("Success!"),
Err(e) => eprintln!("Error: {}", e),
// Output: Error: Something went wrong at [src/main.rs:15:5]
}
}
```
### With `thiserror`
The crate shines when used with `thiserror` for custom error types:
```rust
use error_location::ErrorLocation;
use std::panic::Location;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyError {
#[error("Database error at {location}: {message}")]
Database {
message: String,
location: ErrorLocation,
},
#[error("API error at {location}: {status}")]
Api {
status: u16,
location: ErrorLocation,
},
}
#[track_caller]
fn query_database() -> Result<String, MyError> {
Err(MyError::Database {
message: "Connection failed".to_string(),
location: ErrorLocation::from(Location::caller()),
})
}
#[track_caller]
fn call_api() -> Result<String, MyError> {
Err(MyError::Api {
status: 404,
location: ErrorLocation::from(Location::caller()),
})
}
fn main() {
match query_database() {
Ok(data) => println!("Data: {}", data),
Err(e) => eprintln!("Error: {}", e),
// Output: Error: Database error at [src/main.rs:34:5]: Connection failed
}
}
```
### Creating Helper Functions
You can create helper functions to reduce boilerplate:
```rust
use error_location::ErrorLocation;
use std::panic::Location;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("Error at {location}: {message}")]
WithLocation {
message: String,
location: ErrorLocation,
},
}
#[track_caller]
fn err_loc(message: impl Into<String>) -> AppError {
AppError::WithLocation {
message: message.into(),
location: ErrorLocation::from(Location::caller()),
}
}
#[track_caller]
fn do_work() -> Result<(), AppError> {
Err(err_loc("Work failed"))
}
```
## How It Works
The `ErrorLocation` struct uses Rust's `#[track_caller]` attribute and `std::panic::Location` to capture the file, line, and column where an error is created. This information is stored at compile time, resulting in zero runtime overhead for location tracking.
When you mark a function with `#[track_caller]` and call `Location::caller()`, Rust automatically provides the caller's location information. The `ErrorLocation` struct wraps this in a convenient, Display-friendly format.
## Output Format
The `Display` implementation formats locations as:
```
[file/path.rs:line:column]
```
For example:
```
[src/database/query.rs:42:10]
```
## Why Use This?
While `std::panic::Location` is available in the standard library, this crate provides:
1. **A dedicated type**: Makes it clear when you're working with error locations
2. **Ergonomic Display**: Pre-formatted output that's consistent across your codebase
3. **Documentation**: Clear examples of usage patterns
4. **Semantic meaning**: `ErrorLocation` conveys intent better than raw `Location`
## Minimum Supported Rust Version (MSRV)
This crate requires Rust 1.70 or later.
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.