aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src/chain.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-27 17:46:29 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-27 17:46:29 +0800
commit4f7bd4f6fa5d27cfe703c54aa029a321f40d19fb (patch)
tree97c31ddbb905d8f0e70418b0970ee6420aeac611 /mingling_macros/src/chain.rs
parent6cadc8d39adebbc263e8576c389b5ef491f10ace (diff)
feat(macros): add async mutable resource injection for `#[chain]`
Support `&mut T` resource parameters in async chain functions by using an extract-store pattern that avoids holding mutable borrows across await points. Remove the previous compile-time rejection of this combination.
Diffstat (limited to 'mingling_macros/src/chain.rs')
-rw-r--r--mingling_macros/src/chain.rs29
1 files changed, 6 insertions, 23 deletions
diff --git a/mingling_macros/src/chain.rs b/mingling_macros/src/chain.rs
index 6191d39..5f72422 100644
--- a/mingling_macros/src/chain.rs
+++ b/mingling_macros/src/chain.rs
@@ -2,7 +2,7 @@
use crate::res_injection::{
ResourceInjection, extract_args_info, generate_immut_resource_bindings,
- wrap_body_with_mut_resources,
+ wrap_body_with_mut_resources, wrap_body_with_mut_resources_async,
};
use proc_macro::TokenStream;
use quote::{ToTokens, quote};
@@ -93,7 +93,11 @@ fn generate_proc_fn(
fn_body_stmts
};
- let wrapped_body = wrap_body_with_mut_resources(body_stmts, &mut_resources, program_type);
+ let wrapped_body = if is_async_fn && !mut_resources.is_empty() {
+ wrap_body_with_mut_resources_async(body_stmts, &mut_resources, program_type)
+ } else {
+ wrap_body_with_mut_resources(body_stmts, &mut_resources, program_type)
+ };
// When the function returns `()`, wrap the result with ResultEmpty
let call_or_wrapped = if is_unit_return {
@@ -252,19 +256,6 @@ fn reject_async(sig: &Signature) -> Result<(), proc_macro2::TokenStream> {
Ok(())
}
-/// Ensures no `&mut` resource injection is used in async functions.
-#[cfg(feature = "async")]
-fn reject_mut_in_async(resources: &[ResourceInjection]) -> Result<(), proc_macro2::TokenStream> {
- if let Some(mut_res) = resources.iter().find(|r| r.is_mut) {
- return Err(syn::Error::new(
- mut_res.var_name.span(),
- "Cannot use `&mut` resource injection in async chain function.",
- )
- .to_compile_error());
- }
- Ok(())
-}
-
pub fn chain_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
// Reject non-empty attribute arguments; #[chain] must be bare
if !attr.is_empty() {
@@ -304,14 +295,6 @@ pub fn chain_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
Err(e) => return e.to_compile_error().into(),
};
- // Reject `&mut` in async chains
- #[cfg(feature = "async")]
- if is_async_fn {
- if let Err(err) = reject_mut_in_async(&resources) {
- return err.into();
- }
- }
-
// Prepare building blocks
let sig = &input_fn.sig;
let inputs = &sig.inputs;