Expand description
§comperr
A minimal crate, backed by a single dependency (proc_macro2), for emitting
span-accurate compile-time errors from procedural macros.
§Overview
When writing proc-macros, you often need to emit a compile_error! that
points at a specific location in the user’s source code, but you don’t want to
bloat compilation time by pulling in a massive crate.
The naive approach of formatting a string and calling .parse() loses the span
entirely, because tokens born from a string have no source location. comperr
constructs the error TokenStream token by token, attaching the correct
Span to each one so the compiler diagnostic lands exactly where you
want it.
§Usage
One-shot with the free function:
use proc_macro2::{Span, TokenStream};
pub fn my_macro(input: TokenStream) -> TokenStream {
return comperr::error(Span::call_site(), "something went wrong");
}Or using the Error struct directly:
use proc_macro2::{Span, TokenStream};
pub fn my_macro(input: TokenStream) -> TokenStream {
let e = comperr::Error::new(Span::call_site(), "something went wrong");
return e.to_compile_error();
}Accumulating errors across a validation loop:
use comperr::Error;
use proc_macro2::{Span, TokenStream};
pub fn my_macro(input: TokenStream) -> TokenStream {
let mut errors = Error::empty();
// validate items, combining any errors as you go
for item in parse_items(&input) {
if let Err(e) = validate(item) {
errors.combine(e);
}
}
if !errors.is_empty() {
return errors.to_compile_error();
}
// emit normal output
TokenStream::new()
}Collecting errors from an iterator:
use comperr::Error;
let combined: Error = items
.iter()
.filter_map(|item| validate(item).err())
.collect();
if !combined.is_empty() {
return combined.to_compile_error();
}§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.
§Performance
All work happens at compile time during macro expansion. There is no runtime overhead in your final binary.
Structs§
- Error
- A compile-time error tied to a source location.
Functions§
- error
- Emits a span-accurate compile-time error in one call.