fieldwork_macro/lib.rs
1//! Proc-macro implementation for the fieldwork crate.
2//!
3//! This crate provides the implementation of the [`with_!`](with_) macro.
4//! Users should depend on the `fieldwork` crate instead of this one directly.
5
6use proc_macro::TokenStream;
7
8mod expand;
9mod parse;
10
11/// Field-level borrow splitting macro.
12///
13/// See the [`fieldwork`](https://docs.rs/fieldwork) crate documentation for
14/// detailed usage information.
15///
16/// # Syntax
17///
18/// ```text
19/// with_!(receiver, {
20/// methods {
21/// method_name(&field1, mut field2, copy field3, arg: Type) -> ReturnType {
22/// // method body
23/// }
24/// }
25/// fields {
26/// field_a
27/// mut field_b
28/// }
29/// body {
30/// // code that uses receiver.method_name() and receiver.field_x
31/// }
32/// });
33/// ```
34///
35/// # Field Modes
36///
37/// - `field` or `&field` — shared reference (`&receiver.field`)
38/// - `mut field` — mutable reference (`&mut receiver.field`)
39/// - `copy field` — by value, requires `Copy` trait
40///
41/// # How It Works
42///
43/// The macro:
44/// 1. Extracts fields from the receiver as separate local bindings
45/// 2. Replaces `receiver.method()` calls with inlined method bodies
46/// 3. Replaces `receiver.field` accesses with the local bindings
47///
48/// This allows the borrow checker to see that the borrows are disjoint.
49#[proc_macro]
50pub fn with_(input: TokenStream) -> TokenStream {
51 let input = syn::parse_macro_input!(input as parse::WithInput);
52 match expand::expand(input) {
53 Ok(tokens) => tokens.into(),
54 Err(err) => err.to_compile_error().into(),
55 }
56}