error-location 0.1.0

A lightweight utility for capturing and displaying error locations in Rust
Documentation
  • Coverage
  • 100%
    6 out of 6 items documented0 out of 2 items with examples
  • Size
  • Source code size: 21.18 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.45 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Links
  • TonyMarkham/error-location
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • TonyMarkham

error-location

Crates.io Documentation License Build Status

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:

[dependencies]
error-location = "0.1"

Usage

Basic Usage

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:

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:

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:

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.