<div align="center">
# comperr
[](https://doc.rust-lang.org/edition-guide/rust-2024/)
[](https://crates.io/crates/comperr)
[](https://docs.rs/comperr)
[](https://codeberg.org/razkar/comperr/src/branch/main/LICENSE-MIT)
[](https://codeberg.org/razkar/comperr/src/branch/main/LICENSE-APACHE)
[](https://crates.io/crates/comperr)
[](https://deps.rs/repo/codeberg/razkar/comperr)
[](https://codeberg.org/razkar/comperr)
A minimal, zero dependency crate for emitting span-accurate compile-time errors from procedural macros.
```rust
return error(span, "expected a string literal");
```
</div>
## What is this?
When writing proc-macros, emitting a `compile_error!` the naive way loses the span, meaning the error points at the wrong place in the user's source code. `comperr` constructs the error token by token, attaching the correct span to each one so the diagnostic lands exactly where you want it.
Zero dependencies. Built for proc-macro authors.
## Installation
```sh
cargo add comperr
```
## Quick Start
One-shot with the free function:
```rust
use comperr::error;
use proc_macro2::{Span, TokenStream};
pub fn my_macro(input: TokenStream) -> TokenStream {
return error(Span::call_site(), "something went wrong");
}
```
Or using the `Error` struct directly:
```rust
use comperr::Error;
use proc_macro2::{Span, TokenStream};
pub fn my_macro(input: TokenStream) -> TokenStream {
let e = Error::new(Span::call_site(), "something went wrong");
return e.to_compile_error();
}
```
Batch multiple errors together:
```rust
use comperr::Error;
use proc_macro2::{Span, TokenStream};
pub fn my_macro(input: TokenStream) -> TokenStream {
let mut err = Error::new(Span::call_site(), "first error");
err.combine(Error::new(Span::call_site(), "second error"));
return err.to_compile_error();
}
```
## Features
* **Span-accurate `compile_error!` emission**
* **Free function for one-shot use**
* **`Error` struct for more control**
* **Batch multiple errors with `Error::combine()`**
* **Accepts any `Into<String>` message**
* **One-dep, super lightweight**
## How It Works
Every token in a `TokenStream` carries a `Span` that tells the compiler where in the source code that token came from. When `compile_error!` is invoked, the compiler reads the span off the tokens it receives and uses that to place the diagnostic. By constructing each token manually and calling `.set_span()` on it, the resulting error points at the original source location rather than at a meaningless internal position.
## Requirements
- Rust 2024 edition
- A proc-macro crate (this library is for macro authors, not end users)
## 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.
Cheers, RazkarStudio
© 2026 RazkarStudio. All rights reserved.