Skip to main content

struct_error_macros/
lib.rs

1//! Procedural macro implementations for the `struct_error` crate.
2//!
3//! # ⚠️ **WARNING: UNAUDITED CODE**
4//!
5//! This crate was AI-generated and has not undergone human review. It likely contains bugs and should **NOT** be used in production. The API is subject to change after audit.
6
7use proc_macro::TokenStream;
8
9mod error;
10mod match_error;
11mod sort;
12mod throws;
13mod united_error;
14mod utils;
15
16/// Defines an atomic error struct, automatically deriving `Debug`, `Display`, and `Error`.
17///
18/// Also attaches `#[macro_magic::export_tokens]` so the struct's AST is readable by other
19/// macros (notably `#[throws]` and `match_error!`).
20///
21/// # Syntax
22///
23/// ```ignore
24/// #[error]
25/// pub struct NotFound;
26///
27/// #[error("resource not found: {}", id)]
28/// pub struct NotFound {
29///     pub id: u64,
30/// }
31/// ```
32///
33/// A field may be annotated with `#[error_source]` to implement the `Error::source()` method.
34///
35/// # Examples
36///
37/// ```ignore
38/// use struct_error::error;
39///
40/// #[error("not found: {}", id)]
41/// pub struct NotFound {
42///     pub id: u64,
43/// }
44///
45/// #[error("IO failed")]
46/// pub struct IoError {
47///     #[error_source]
48///     pub inner: std::io::Error,
49/// }
50/// ```
51#[proc_macro_attribute]
52pub fn error(attr: TokenStream, item: TokenStream) -> TokenStream {
53    error::error(attr, item)
54}
55
56/// Defines a compile-time alias for a set of errors (a *united error*).
57///
58/// The generated struct is a zero-sized type (ZST) that carries no runtime data. It serves
59/// purely as a named grouping of error types, allowing `#[throws]` and `match_error!` to
60/// refer to the whole set at once.
61///
62/// # Syntax
63///
64/// ```ignore
65/// use struct_error::united_error;
66///
67/// #[united_error(NotFound, Timeout)]
68/// pub struct AppError;
69/// ```
70///
71/// # Examples
72///
73/// ```ignore
74/// use struct_error::{error, united_error, throws, match_error, throw};
75///
76/// #[error]
77/// pub struct NotFound;
78///
79/// #[error]
80/// pub struct Timeout;
81///
82/// #[united_error(NotFound, Timeout)]
83/// pub struct AppError;
84///
85/// #[throws(AppError)]
86/// fn risky() {
87///     throw!(NotFound);
88/// }
89/// ```
90#[proc_macro_attribute]
91pub fn united_error(attr: TokenStream, item: TokenStream) -> TokenStream {
92    united_error::united_error(attr, item)
93}
94
95/// Replaces the function's return type with an implicit error union and rewrites control flow.
96///
97/// `#[throws]` performs a two-phase expansion:
98/// 1. **Phase 1** — collects AST tokens from each listed error type via `macro_magic::forward_tokens!`.
99/// 2. **Phase 2** — deduplicates and blind-sorts the error paths, generates the `Unt` HList
100///    return type, injects a local `__StructErrorInto` trait, and rewrites the function body
101///    to intercept `?` operators and wrap successful returns in `Ok(...)`.
102///
103/// # Syntax
104///
105/// ```ignore
106/// #[throws(ErrorA, ErrorB, ErrorC)]
107/// pub fn foo() -> T { ... }
108/// ```
109///
110/// The original return type `T` is preserved; the function implicitly returns
111/// `Result<T, Unt<ErrorA, Unt<ErrorB, Unt<ErrorC, End>>>>`.
112///
113/// # Examples
114///
115/// ```ignore
116/// use struct_error::{error, throws, throw};
117///
118/// #[error]
119/// pub struct NotFound;
120///
121/// #[throws(NotFound)]
122/// pub fn fetch(id: u64) -> String {
123///     if id == 0 {
124///         throw!(NotFound);
125///     }
126///     format!("resource-{}", id)
127/// }
128/// ```
129#[proc_macro_attribute]
130pub fn throws(attr: TokenStream, item: TokenStream) -> TokenStream {
131    throws::throws(attr, item)
132}
133
134/// Blind, type-driven pattern matching on errors.
135///
136/// Eliminates manual `Result` and `Unt` nesting by matching error types directly.
137/// Error arms are sorted automatically using the same blind sorting algorithm as `#[throws]`,
138/// guaranteeing that declaration sites and match sites agree on the `Unt` nesting order.
139///
140/// Catch-all patterns (`_` or bare bindings) are **not allowed**; the compiler enforces
141/// exhaustiveness through the uninhabited `End` terminator.
142///
143/// # Syntax
144///
145/// ```ignore
146/// match_error!(expr {
147///     Ok(v) => ...,
148///     NotFound => ...,
149///     Timeout { ms } => ...,
150/// })
151/// ```
152///
153/// The `Ok(...)` arm is preserved as-is. Error arms may use unit structs, struct
154/// destructuring, or tuple-struct patterns. All error types in the implicit union must be
155/// matched explicitly.
156///
157/// # Examples
158///
159/// ```ignore
160/// use struct_error::{error, throws, match_error, throw};
161///
162/// #[error]
163/// pub struct NotFound;
164///
165/// #[error]
166/// pub struct Timeout;
167///
168/// #[throws(NotFound, Timeout)]
169/// fn risky() -> i32 {
170///     throw!(NotFound);
171///     42
172/// }
173///
174/// fn main() {
175///     let r = risky();
176///     match_error!(r {
177///         Ok(v) => println!("{}", v),
178///         NotFound => println!("not found"),
179///         Timeout => println!("timeout"),
180///     });
181/// }
182/// ```
183#[proc_macro]
184pub fn match_error(input: TokenStream) -> TokenStream {
185    match_error::match_error(input)
186}
187
188/// Internal attribute macro used as the CPS callback for `macro_magic::forward_tokens!`.
189///
190/// Receives a forwarded item together with accumulated state (remaining paths, accumulator,
191/// function metadata), chains the next `forward_tokens!` call if paths remain, or calls
192/// `__throws_impl` when all tokens have been collected.
193///
194/// This macro is **not** intended for direct use.
195#[proc_macro_attribute]
196pub fn __throws_cps(attr: TokenStream, item: TokenStream) -> TokenStream {
197    throws::__throws_cps(attr, item)
198}
199
200/// Internal function-like proc macro called by `__throws_cps` at the end of the token
201/// forwarding chain.
202///
203/// Receives all collected forwarded tokens plus the original function signature and body,
204/// then performs the actual signature rewriting and AST transformation.
205///
206/// This macro is **not** intended for direct use.
207#[proc_macro]
208pub fn __throws_impl(input: TokenStream) -> TokenStream {
209    throws::__throws_impl(input)
210}
211
212/// Internal attribute macro that encodes the member list on structs generated by
213/// `#[united_error]`.
214///
215/// The compiler ignores this attribute; it is only read by `__throws_impl` when parsing
216/// forwarded tokens to expand a united error into its constituent types.
217///
218/// This macro is **not** intended for direct use.
219#[proc_macro_attribute]
220pub fn __struct_error_members(_attr: TokenStream, item: TokenStream) -> TokenStream {
221    item
222}