aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeicao-CatilGrass <1992414357@qq.com>2026-05-23 21:12:43 +0800
committerWeicao-CatilGrass <1992414357@qq.com>2026-05-23 21:17:54 +0800
commit47c96bb31b2398d28bf50406f79e2713030d2d4c (patch)
treeaa426743010c9a946b5a34dcbc419e831a481c2e
parent4836fceada0d9a87a82e1f2b011b3f9f5956dc4c (diff)
Refactor resource injection to use inline mut resource wrapping
-rw-r--r--mingling_macros/src/renderer.rs45
1 files changed, 26 insertions, 19 deletions
diff --git a/mingling_macros/src/renderer.rs b/mingling_macros/src/renderer.rs
index 7f85a60..ae75895 100644
--- a/mingling_macros/src/renderer.rs
+++ b/mingling_macros/src/renderer.rs
@@ -4,9 +4,7 @@ use syn::spanned::Spanned;
use syn::{ItemFn, ReturnType, Signature, Type, TypePath, parse_macro_input};
use crate::get_global_set;
-use crate::res_injection::{
- extract_args_info, generate_immut_resource_bindings, wrap_body_with_mut_resources,
-};
+use crate::res_injection::{extract_args_info, generate_immut_resource_bindings};
/// Extracts and returns the return type from the function signature (or None for `()` / no return type).
fn extract_return_type(sig: &Signature) -> syn::Result<Option<syn::Type>> {
@@ -78,6 +76,7 @@ pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
let struct_name = syn::Ident::new(&internal_name, fn_name.span());
let has_resources = !resources.is_empty();
+ let has_mut_resources = resources.iter().any(|r| r.is_mut);
// Generate resource bindings for immutable resources
let immut_resource_stmts = generate_immut_resource_bindings(resources.iter(), program_type);
@@ -103,30 +102,38 @@ pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
}
};
- // Build the Renderer::render body with resource injection
- let render_fn_body = if has_resources {
- let wrapped_body =
- wrap_body_with_mut_resources(&fn_body_stmts, &mut_resources, program_type);
- quote! {
- #(#immut_resource_stmts)*
- #wrapped_body
+ let inner_body_with_resources = if has_mut_resources {
+ let mut wrapped = quote! { #(#fn_body_stmts)* };
+ for res in mut_resources.iter().rev() {
+ let var_name = &res.var_name;
+ let inner_type = &res.inner_type;
+ wrapped = quote! {
+ ::mingling::this::<#program_type>().modify_res(|#var_name: &mut #inner_type| {
+ #wrapped
+ })
+ };
}
+ wrapped
} else {
quote! { #(#fn_body_stmts)* }
};
- // Build the original function with resource injection - use the resource bindings directly
- // from the function parameters rather than re-fetching from context.
- let original_fn_body = if has_resources {
+ // Build the Renderer::render body with resource injection
+ // Renderer::render returns (), output goes through __renderer_inner_result parameter.
+ // Resources are injected from the program context here.
+ let render_fn_body = if has_resources {
quote! {
- let mut dummy_r = ::mingling::RenderResult::default();
- {
- let __renderer_inner_result = &mut dummy_r;
- #(#fn_body_stmts)*
- }
- #result_return
+ #(#immut_resource_stmts)*
+ #inner_body_with_resources
}
} else {
+ quote! { #inner_body_with_resources }
+ };
+
+ // Build the original function body
+ // The original function preserves the user's signature and return type.
+ // Resource parameters are passed directly by the caller, NOT injected from context.
+ let original_fn_body = {
quote! {
let mut dummy_r = ::mingling::RenderResult::default();
{