Skip to main content

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}