From 4f7bd4f6fa5d27cfe703c54aa029a321f40d19fb Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 27 Jun 2026 17:46:29 +0800 Subject: 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. --- mingling_core/src/asset/global_resource.rs | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'mingling_core') diff --git a/mingling_core/src/asset/global_resource.rs b/mingling_core/src/asset/global_resource.rs index 83a779d..651655a 100644 --- a/mingling_core/src/asset/global_resource.rs +++ b/mingling_core/src/asset/global_resource.rs @@ -74,6 +74,44 @@ where } } + /// Internal syntax for the `&mut MyResource` syntax of async #[chain], do not use directly. + /// + /// Extracts a mutable resource from the global store (clone-out), returning an + /// owned value. The caller must call [`__store_res`] to write back modifications. + #[doc(hidden)] + #[must_use] + pub fn __extract_res_mut( + &self, + ) -> Res { + let Ok(mut guard) = self.resources.lock() else { + return Res::res_default(); + }; + if let Some(arc_res) = guard + .get_mut(&TypeId::of::()) + .and_then(|a| a.downcast_mut::>()) + { + match Arc::try_unwrap(std::mem::take(arc_res)) { + Ok(val) => val, + Err(arc) => (*arc).res_clone(), + } + } else { + Res::res_default() + } + } + + /// Internal syntax for the `&mut MyResource` syntax of async #[chain], do not use directly. + /// + /// Stores a modified resource value back into the global store. + #[doc(hidden)] + pub fn __store_res( + &self, + val: Res, + ) { + if let Ok(mut guard) = self.resources.lock() { + guard.insert(TypeId::of::(), Box::new(Arc::new(val))); + } + } + /// Get an resources by type, returning `Res` if present #[must_use] pub fn res(&self) -> Option> { -- cgit