Skip to main content

rust_key_paths/
async_lock.rs

1//! # Async Lock Keypath Module
2//!
3//! This module provides `AsyncLockKp` for safely navigating through async locked/synchronized data structures.
4//!
5//! # Naming convention (aligned with [crate::lock::LockKp] and [crate::Kp])
6//!
7//! - **`then`** – chain with a plain [crate::Kp]
8//! - **`then_lock`** – chain with a sync [crate::lock::LockKp]
9//! - **`then_async`** – chain with another async keypath (e.g. tokio RwLock)
10//! - **`then_pin_future`** – chain with a #[pin] Future field await ([crate::pin])
11//!
12//! Example: `root_lock.then_lock(parking_kp).then_async(async_kp).then_lock(std_lock_kp)`
13//!
14//! # SHALLOW CLONING GUARANTEE
15//!
16//! **IMPORTANT**: All cloning operations in this module are SHALLOW (reference-counted) clones:
17//!
18//! 1. **`AsyncLockKp` derives `Clone`**: Clones function pointers and PhantomData only
19//!    - `prev` and `next` fields contain function pointers (cheap to copy)
20//!    - `mid` field is typically just `PhantomData<T>` (zero-sized, zero-cost)
21//!    - No heap allocations or deep data copies
22//!
23//! 2. **`Lock: Clone` bound** (e.g., `Arc<tokio::sync::Mutex<T>>`):
24//!    - For `Arc<T>`: Only increments the atomic reference count (one atomic operation)
25//!    - The actual data `T` inside is **NEVER** cloned
26//!    - This is the whole point of Arc - shared ownership without copying data
27//!
28//! 3. **`L: Clone` bound** (e.g., `TokioMutexAccess<T>`):
29//!    - Only clones `PhantomData<T>` which is zero-sized
30//!    - Compiled away completely - zero runtime cost
31
32use crate::Kp;
33use async_trait::async_trait;
34use std::sync::Arc;
35
36// Re-export tokio sync types for convenience
37#[cfg(feature = "tokio")]
38pub use tokio::sync::{Mutex as TokioMutex, RwLock as TokioRwLock};
39
40// =============================================================================
41// Why two traits: AsyncLockLike and AsyncKeyPathLike
42// =============================================================================
43//
44// - AsyncLockLike<Lock, Inner>: One "step" through a lock. Given a Lock (e.g.
45//   Arc<Mutex<T>>), it async yields Inner (e.g. &T). Used by the `mid` field of
46//   AsyncLockKp to go from "container" to "value inside the lock". Implemented
47//   by TokioMutexAccess, TokioRwLockAccess, etc.
48//
49// - AsyncKeyPathLike<Root, MutRoot>: A full keypath from Root to a value. Used
50//   so we can chain at any depth: both AsyncLockKp and ComposedAsyncLockKp
51//   implement it, so we can write `kp1.then_async(kp2).then_async(kp3).get(&root)`.
52//   Without this trait we could not express "first and second can be either a
53//   single AsyncLockKp or another ComposedAsyncLockKp" in the type system.
54
55/// Async trait for types that can provide async lock/unlock behavior
56/// Converts from a Lock type to Inner or InnerMut value asynchronously
57#[async_trait]
58pub trait AsyncLockLike<Lock, Inner>: Send + Sync {
59    /// Get immutable access to the inner value asynchronously
60    async fn lock_read(&self, lock: &Lock) -> Option<Inner>;
61
62    /// Get mutable access to the inner value asynchronously
63    async fn lock_write(&self, lock: &mut Lock) -> Option<Inner>;
64}
65
66/// Sync keypath that can be used as the "second" in [AsyncLockKpThenLockKp] for blanket impls.
67/// Also implemented for [crate::Kp] so [crate::Kp::then_lock] and [crate::Kp::then_async] can chain.
68pub trait SyncKeyPathLike<Root, Value, MutRoot, MutValue> {
69    /// Get an immutable reference through the keypath (sync, non-blocking).
70    ///
71    /// For [crate::lock::LockKp], this acquires a read/write lock and returns the value.
72    /// For plain [crate::Kp], this navigates to the field directly.
73    ///
74    /// # Example
75    /// ```
76    /// use rust_key_paths::async_lock::SyncKeyPathLike;
77    /// use rust_key_paths::{KpType, LockKp};
78    /// use std::sync::Mutex;
79    ///
80    /// #[derive(key_paths_derive::Kp)]
81    /// struct WithLocks {
82    ///     std_mutex: std::sync::Mutex<i32>,
83    ///     std_rwlock: std::sync::RwLock<String>,
84    /// }
85    ///
86    /// let locks = WithLocks {
87    ///     std_mutex: Mutex::new(99),
88    ///     std_rwlock: std::sync::RwLock::new("hello".to_string()),
89    /// };
90    /// let mutex_kp = WithLocks::std_mutex();
91    /// let rwlock_kp = WithLocks::std_rwlock();
92    /// let next: KpType<i32, i32> = rust_key_paths::Kp::new(|i: &i32| Some(i), |i: &mut i32| Some(i));
93    /// let lock_kp = LockKp::new(mutex_kp, rust_key_paths::StdMutexAccess::new(), next);
94    ///
95    /// // sync_get works with LockKp (same as .get())
96    /// let value = lock_kp.sync_get(&locks).unwrap();
97    /// assert_eq!(*value, 99);
98    /// ```
99    fn sync_get(&self, root: Root) -> Option<Value>;
100
101    /// Get a mutable reference through the keypath (sync, non-blocking).
102    ///
103    /// For [crate::lock::LockKp], this acquires a write lock and returns a mutable reference.
104    /// For plain [crate::Kp], this navigates to the field mutably.
105    ///
106    /// # Example
107    /// ```
108    /// use rust_key_paths::async_lock::SyncKeyPathLike;
109    /// use rust_key_paths::{KpType, LockKp};
110    /// use std::sync::Mutex;
111    ///
112    /// #[derive(key_paths_derive::Kp)]
113    /// struct WithLocks {
114    ///     std_mutex: std::sync::Mutex<i32>,
115    ///     std_rwlock: std::sync::RwLock<String>,
116    /// }
117    ///
118    /// let mut locks = WithLocks {
119    ///     std_mutex: Mutex::new(99),
120    ///     std_rwlock: std::sync::RwLock::new("hello".to_string()),
121    /// };
122    /// let mutex_kp = WithLocks::std_mutex();
123    /// let next: KpType<i32, i32> = rust_key_paths::Kp::new(|i: &i32| Some(i), |i: &mut i32| Some(i));
124    /// let lock_kp = LockKp::new(mutex_kp, rust_key_paths::StdMutexAccess::new(), next);
125    ///
126    /// // sync_get_mut works with LockKp (same as .get_mut())
127    /// let value = lock_kp.sync_get_mut(&mut locks).unwrap();
128    /// *value = 42;
129    /// assert_eq!(*locks.std_mutex.lock().unwrap(), 42);
130    /// ```
131    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue>;
132}
133
134impl<R, V, Root, Value, MutRoot, MutValue, G, S> SyncKeyPathLike<Root, Value, MutRoot, MutValue>
135    for crate::Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
136where
137    Root: std::borrow::Borrow<R>,
138    Value: std::borrow::Borrow<V>,
139    MutRoot: std::borrow::BorrowMut<R>,
140    MutValue: std::borrow::BorrowMut<V>,
141    G: Fn(Root) -> Option<Value>,
142    S: Fn(MutRoot) -> Option<MutValue>,
143{
144    fn sync_get(&self, root: Root) -> Option<Value> {
145        self.get(root)
146    }
147    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
148        self.get_mut(root)
149    }
150}
151
152impl<
153        R,
154        Lock,
155        Mid,
156        V,
157        Root,
158        LockValue,
159        MidValue,
160        Value,
161        MutRoot,
162        MutLock,
163        MutMid,
164        MutValue,
165        G1,
166        S1,
167        L,
168        G2,
169        S2,
170    >
171    SyncKeyPathLike<Root, Value, MutRoot, MutValue> for crate::lock::LockKp<
172        R,
173        Lock,
174        Mid,
175        V,
176        Root,
177        LockValue,
178        MidValue,
179        Value,
180        MutRoot,
181        MutLock,
182        MutMid,
183        MutValue,
184        G1,
185        S1,
186        L,
187        G2,
188        S2,
189    >
190where
191    Root: std::borrow::Borrow<R>,
192    LockValue: std::borrow::Borrow<Lock>,
193    MidValue: std::borrow::Borrow<Mid>,
194    Value: std::borrow::Borrow<V>,
195    MutRoot: std::borrow::BorrowMut<R>,
196    MutLock: std::borrow::BorrowMut<Lock>,
197    MutMid: std::borrow::BorrowMut<Mid>,
198    MutValue: std::borrow::BorrowMut<V>,
199    G1: Fn(Root) -> Option<LockValue>,
200    S1: Fn(MutRoot) -> Option<MutLock>,
201    L: crate::lock::LockAccess<Lock, MidValue> + crate::lock::LockAccess<Lock, MutMid>,
202    G2: Fn(MidValue) -> Option<Value>,
203    S2: Fn(MutMid) -> Option<MutValue>,
204    V: Clone,
205{
206    #[inline]
207    fn sync_get(&self, root: Root) -> Option<Value> {
208        self.get(root)
209    }
210    #[inline]
211    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
212        self.get_mut(root)
213    }
214}
215
216/// Trait for async keypaths (both [AsyncLockKp] and [ComposedAsyncLockKp]) so composition can be any depth.
217///
218/// # Why MutRoot? (RwLock/Mutex interior mutability)
219///
220/// RwLock and Mutex provide **interior mutability**—their `lock()` / `write()` methods take `&self`,
221/// so you can mutate through an immutable reference. For **async lock keypaths**, the mutation
222/// happens inside the lock; you do *not* need a mutable root. `MutRoot` exists for composition
223/// with sync keypaths (e.g. [Kp]) that may require `&mut` along the path. When the path goes
224/// entirely through locks (RwLock/Mutex), `Root` and `MutRoot` are typically the same type
225/// (e.g. `&Root` for both).
226#[async_trait(?Send)]
227pub trait AsyncKeyPathLike<Root, MutRoot> {
228    /// Value type at the end of the keypath.
229    type Value;
230    /// Mutable value type at the end of the keypath.
231    type MutValue;
232    /// Get the value at the end of the keypath.
233    async fn get(&self, root: Root) -> Option<Self::Value>;
234    /// Get mutable access to the value at the end of the keypath.
235    async fn get_mut(&self, root: MutRoot) -> Option<Self::MutValue>;
236}
237
238/// An async keypath that handles async locked values (e.g., Arc<tokio::sync::Mutex<T>>)
239///
240/// Structure:
241/// - `prev`: Keypath from Root to Lock container (e.g., Arc<tokio::sync::Mutex<Mid>>)
242/// - `mid`: Async lock access handler that goes from Lock to Inner value
243/// - `next`: Keypath from Inner value to final Value
244///
245/// # Type Parameters
246/// - `R`: Root type (base)
247/// - `Lock`: Lock container type (e.g., Arc<tokio::sync::Mutex<Mid>>)
248/// - `Mid`: The type inside the lock
249/// - `V`: Final value type
250/// - Rest are the same generic parameters as Kp
251///
252/// # Cloning Behavior
253///
254/// **IMPORTANT**: All `Clone` operations in this struct are SHALLOW clones:
255///
256/// - `AsyncLockKp` itself derives `Clone` - this clones the three field references/closures
257/// - `prev` and `next` fields are `Kp` structs containing function pointers (cheap to clone)
258/// - `mid` field implements `AsyncLockLike` trait - typically just `PhantomData` (zero-cost clone)
259/// - When `Lock: Clone` (e.g., `Arc<tokio::sync::Mutex<T>>`), cloning is just incrementing reference count
260/// - NO deep data cloning occurs - all clones are pointer/reference increments
261#[derive(Clone)] // SHALLOW: Clones function pointers and PhantomData only
262pub struct AsyncLockKp<
263    R,
264    Lock,
265    Mid,
266    V,
267    Root,
268    LockValue,
269    MidValue,
270    Value,
271    MutRoot,
272    MutLock,
273    MutMid,
274    MutValue,
275    G1,
276    S1,
277    L,
278    G2,
279    S2,
280> where
281    Root: std::borrow::Borrow<R>,
282    LockValue: std::borrow::Borrow<Lock>,
283    MidValue: std::borrow::Borrow<Mid>,
284    Value: std::borrow::Borrow<V>,
285    MutRoot: std::borrow::BorrowMut<R>,
286    MutLock: std::borrow::BorrowMut<Lock>,
287    MutMid: std::borrow::BorrowMut<Mid>,
288    MutValue: std::borrow::BorrowMut<V>,
289    G1: Fn(Root) -> Option<LockValue> + Clone,
290    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
291    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
292    G2: Fn(MidValue) -> Option<Value> + Clone,
293    S2: Fn(MutMid) -> Option<MutValue> + Clone,
294{
295    /// Keypath from Root to Lock container
296    pub(crate) prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
297
298    /// Async lock access handler (converts Lock -> Inner)
299    pub(crate) mid: L,
300
301    /// Keypath from Inner to final Value
302    pub(crate) next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
303}
304
305impl<
306    R,
307    Lock,
308    Mid,
309    V,
310    Root,
311    LockValue,
312    MidValue,
313    Value,
314    MutRoot,
315    MutLock,
316    MutMid,
317    MutValue,
318    G1,
319    S1,
320    L,
321    G2,
322    S2,
323>
324    AsyncLockKp<
325        R,
326        Lock,
327        Mid,
328        V,
329        Root,
330        LockValue,
331        MidValue,
332        Value,
333        MutRoot,
334        MutLock,
335        MutMid,
336        MutValue,
337        G1,
338        S1,
339        L,
340        G2,
341        S2,
342    >
343where
344    Root: std::borrow::Borrow<R>,
345    LockValue: std::borrow::Borrow<Lock>,
346    MidValue: std::borrow::Borrow<Mid>,
347    Value: std::borrow::Borrow<V>,
348    MutRoot: std::borrow::BorrowMut<R>,
349    MutLock: std::borrow::BorrowMut<Lock>,
350    MutMid: std::borrow::BorrowMut<Mid>,
351    MutValue: std::borrow::BorrowMut<V>,
352    G1: Fn(Root) -> Option<LockValue> + Clone,
353    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
354    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
355    G2: Fn(MidValue) -> Option<Value> + Clone,
356    S2: Fn(MutMid) -> Option<MutValue> + Clone,
357{
358    /// Create a new AsyncLockKp with prev, mid, and next components
359    pub fn new(
360        prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
361        mid: L,
362        next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
363    ) -> Self {
364        Self { prev, mid, next }
365    }
366
367    /// Get the value through the lock
368    ///
369    /// This will:
370    /// 1. Use `prev` to get to the Lock
371    /// 2. Use `mid` to asynchronously lock and get the Inner value
372    /// 3. Use `next` to get to the final Value
373    ///
374    /// # SHALLOW CLONING NOTE
375    ///
376    /// When `lock` is cloned (e.g., `Arc<tokio::sync::Mutex<T>>`):
377    /// - Only the Arc reference count is incremented (one atomic operation)
378    /// - The actual data `T` inside the Mutex is **NEVER** cloned
379    /// - This is safe and efficient - the whole point of Arc
380    #[inline]
381    pub async fn get(&self, root: Root) -> Option<Value>
382    where
383        Lock: Clone,
384    {
385        // SHALLOW CLONE: For Arc<Mutex<T>>, only increments Arc refcount
386        // The actual data T is NOT cloned
387        let lock_value = (self.prev.get)(root)?;
388        let lock: &Lock = lock_value.borrow();
389        let lock_clone = lock.clone(); // SHALLOW: Arc refcount++
390
391        // Async lock and get the mid value
392        let mid_value = self.mid.lock_read(&lock_clone).await?;
393
394        // Navigate from mid to final value
395        (self.next.get)(mid_value)
396    }
397
398    /// Get mutable access to the value through the lock
399    #[inline]
400    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue>
401    where
402        Lock: Clone,
403    {
404        // SHALLOW CLONE: For Arc<Mutex<T>>, only increments Arc refcount
405        let mut lock_value = (self.prev.set)(root)?;
406        let lock: &mut Lock = lock_value.borrow_mut();
407        let mut lock_clone = lock.clone(); // SHALLOW: Arc refcount++
408
409        // Async lock and get the mid value
410        let mid_value = self.mid.lock_write(&mut lock_clone).await?;
411
412        // Navigate from mid to final value
413        (self.next.set)(mid_value)
414    }
415
416    /// Set the value through the lock using an updater function.
417    ///
418    /// Uses interior mutability—no mutable root required. RwLock/Mutex allow mutation through
419    /// `&self` (lock().write() etc.), so `root` can be `&Root`.
420    ///
421    /// Internally uses: `prev.get` → `mid.lock_read`/`lock_write` → `next.set` (the setter path).
422    pub async fn set<F>(&self, root: Root, updater: F) -> Result<(), String>
423    where
424        Lock: Clone,
425        F: FnOnce(&mut V),
426    {
427        // SHALLOW CLONE: For Arc<Mutex<T>>, only increments Arc refcount
428        let lock_value = (self.prev.get)(root).ok_or("Failed to get lock from root")?;
429        let lock: &Lock = lock_value.borrow();
430        let lock_clone = lock.clone(); // SHALLOW: Arc refcount++
431
432        // Async lock and get the mid value
433        let mut mid_value = self
434            .mid
435            .lock_read(&lock_clone)
436            .await
437            .ok_or("Failed to lock")?;
438
439        // Get the final value
440        let mut mut_value = (self.next.set)(mid_value).ok_or("Failed to navigate to value")?;
441        let v: &mut V = mut_value.borrow_mut();
442
443        // Apply the updater
444        updater(v);
445
446        Ok(())
447    }
448
449    // ========================================================================
450    // Interoperability: then (Kp), then_lock (sync LockKp), then_async (async keypath)
451    // ========================================================================
452
453    /// Chain this AsyncLockKp with a regular [crate::Kp] (no root at call site).
454    /// Returns an AsyncLockKp that goes one step further; use [AsyncLockKp::get] or [AsyncLockKp::get_mut] with root later.
455    ///
456    /// # Example
457    /// ```ignore
458    /// // Root -> Arc<tokio::Mutex<Inner>> -> Inner -> field
459    /// let async_kp = AsyncLockKp::new(root_to_lock, TokioMutexAccess::new(), lock_to_inner);
460    /// let field_kp = Kp::new(|inner: &Inner| Some(&inner.field), |inner: &mut Inner| Some(&mut inner.field));
461    /// let chained = async_kp.then(field_kp);
462    /// let result = chained.get(&root).await;
463    /// ```
464    pub fn then<V2, Value2, MutValue2, G3, S3>(
465        self,
466        next_kp: crate::Kp<V, V2, Value, Value2, MutValue, MutValue2, G3, S3>,
467    ) -> AsyncLockKp<
468        R,
469        Lock,
470        Mid,
471        V2,
472        Root,
473        LockValue,
474        MidValue,
475        Value2,
476        MutRoot,
477        MutLock,
478        MutMid,
479        MutValue2,
480        G1,
481        S1,
482        L,
483        impl Fn(MidValue) -> Option<Value2> + Clone + use<G1, G2, G3, L, Lock, LockValue, Mid, MidValue, MutLock, MutMid, MutRoot, MutValue, MutValue2, R, Root, S1, S2, S3, Value, Value2, V, V2>,
484        impl Fn(MutMid) -> Option<MutValue2> + Clone + use<G1, G2, G3, L, Lock, LockValue, Mid, MidValue, MutLock, MutMid, MutRoot, MutValue, MutValue2, R, Root, S1, S2, S3, Value, Value2, V, V2>,
485    >
486    where
487        V: 'static,
488        V2: 'static,
489        Value: std::borrow::Borrow<V>,
490        Value2: std::borrow::Borrow<V2>,
491        MutValue: std::borrow::BorrowMut<V>,
492        MutValue2: std::borrow::BorrowMut<V2>,
493        G3: Fn(Value) -> Option<Value2> + Clone,
494        S3: Fn(MutValue) -> Option<MutValue2> + Clone,
495    {
496        let next_get = self.next.get;
497        let next_set = self.next.set;
498        let chained_kp = crate::Kp::new(
499            move |mid_value: MidValue| next_get(mid_value).and_then(|v| (next_kp.get)(v)),
500            move |mid_value: MutMid| next_set(mid_value).and_then(|v| (next_kp.set)(v)),
501        );
502        AsyncLockKp::new(self.prev, self.mid, chained_kp)
503    }
504
505    /// Chain this AsyncLockKp with a sync [crate::lock::LockKp] (no root at call site).
506    /// Returns a keypath that first goes through the async lock, then through the sync lock; use `.get(&root).await` later.
507    pub fn then_lock<
508        Lock2,
509        Mid2,
510        V2,
511        LockValue2,
512        MidValue2,
513        Value2,
514        MutLock2,
515        MutMid2,
516        MutValue2,
517        G2_1,
518        S2_1,
519        L2,
520        G2_2,
521        S2_2,
522    >(
523        self,
524        lock_kp: crate::lock::LockKp<
525            V,
526            Lock2,
527            Mid2,
528            V2,
529            Value,
530            LockValue2,
531            MidValue2,
532            Value2,
533            MutValue,
534            MutLock2,
535            MutMid2,
536            MutValue2,
537            G2_1,
538            S2_1,
539            L2,
540            G2_2,
541            S2_2,
542        >,
543    ) -> AsyncLockKpThenLockKp<
544        R,
545        V2,
546        Root,
547        Value2,
548        MutRoot,
549        MutValue2,
550        Self,
551        crate::lock::LockKp<
552            V,
553            Lock2,
554            Mid2,
555            V2,
556            Value,
557            LockValue2,
558            MidValue2,
559            Value2,
560            MutValue,
561            MutLock2,
562            MutMid2,
563            MutValue2,
564            G2_1,
565            S2_1,
566            L2,
567            G2_2,
568            S2_2,
569        >,
570    >
571    where
572        V: 'static,
573        V2: 'static,
574        Value: std::borrow::Borrow<V>,
575        Value2: std::borrow::Borrow<V2>,
576        MutValue: std::borrow::BorrowMut<V>,
577        MutValue2: std::borrow::BorrowMut<V2>,
578        LockValue2: std::borrow::Borrow<Lock2>,
579        MidValue2: std::borrow::Borrow<Mid2>,
580        MutLock2: std::borrow::BorrowMut<Lock2>,
581        MutMid2: std::borrow::BorrowMut<Mid2>,
582        G2_1: Fn(Value) -> Option<LockValue2>,
583        S2_1: Fn(MutValue) -> Option<MutLock2>,
584        L2: crate::lock::LockAccess<Lock2, MidValue2> + crate::lock::LockAccess<Lock2, MutMid2>,
585        G2_2: Fn(MidValue2) -> Option<Value2>,
586        S2_2: Fn(MutMid2) -> Option<MutValue2>,
587    {
588        AsyncLockKpThenLockKp {
589            first: self,
590            second: lock_kp,
591            _p: std::marker::PhantomData,
592        }
593    }
594
595    /// Chain with another async keypath (like [crate::lock::LockKp::then_lock] for sync locks).
596    ///
597    /// Chain with another async keypath (e.g. tokio RwLock). Use [ComposedAsyncLockKp::get] or
598    /// [ComposedAsyncLockKp::get_mut] with root later.
599    ///
600    /// Root -> AsyncLock1 -> Container -> AsyncLock2 -> Value
601    ///
602    /// # Example
603    /// ```ignore
604    /// // Root -> Arc<tokio::Mutex<Container>> -> Container -> Arc<tokio::Mutex<Value>> -> Value
605    /// let async_kp1 = AsyncLockKp::new(...); // Root -> Container
606    /// let async_kp2 = AsyncLockKp::new(...); // Container -> Value
607    /// let chained = async_kp1.then_async(async_kp2);
608    /// let result = chained.get(&root).await;
609    /// ```
610    pub fn then_async<
611        Lock2,
612        Mid2,
613        V2,
614        LockValue2,
615        MidValue2,
616        Value2,
617        MutLock2,
618        MutMid2,
619        MutValue2,
620        G2_1,
621        S2_1,
622        L2,
623        G2_2,
624        S2_2,
625    >(
626        self,
627        other: AsyncLockKp<
628            V,
629            Lock2,
630            Mid2,
631            V2,
632            Value,
633            LockValue2,
634            MidValue2,
635            Value2,
636            MutValue,
637            MutLock2,
638            MutMid2,
639            MutValue2,
640            G2_1,
641            S2_1,
642            L2,
643            G2_2,
644            S2_2,
645        >,
646    ) -> ComposedAsyncLockKp<
647        R,
648        V2,
649        Root,
650        Value2,
651        MutRoot,
652        MutValue2,
653        Self,
654        AsyncLockKp<
655            V,
656            Lock2,
657            Mid2,
658            V2,
659            Value,
660            LockValue2,
661            MidValue2,
662            Value2,
663            MutValue,
664            MutLock2,
665            MutMid2,
666            MutValue2,
667            G2_1,
668            S2_1,
669            L2,
670            G2_2,
671            S2_2,
672        >,
673    >
674    where
675        Lock: Clone,
676        Lock2: Clone,
677        V: 'static,
678        V2: 'static,
679        Value: std::borrow::Borrow<V>,
680        LockValue2: std::borrow::Borrow<Lock2>,
681        MidValue2: std::borrow::Borrow<Mid2>,
682        Value2: std::borrow::Borrow<V2>,
683        MutValue: std::borrow::BorrowMut<V>,
684        MutLock2: std::borrow::BorrowMut<Lock2>,
685        MutMid2: std::borrow::BorrowMut<Mid2>,
686        MutValue2: std::borrow::BorrowMut<V2>,
687        G2_1: Fn(Value) -> Option<LockValue2> + Clone,
688        S2_1: Fn(MutValue) -> Option<MutLock2> + Clone,
689        L2: AsyncLockLike<Lock2, MidValue2> + AsyncLockLike<Lock2, MutMid2> + Clone,
690        G2_2: Fn(MidValue2) -> Option<Value2> + Clone,
691        S2_2: Fn(MutMid2) -> Option<MutValue2> + Clone,
692    {
693        ComposedAsyncLockKp {
694            first: self,
695            second: other,
696            _p: std::marker::PhantomData,
697        }
698    }
699}
700
701// Implement AsyncKeyPathLike for AsyncLockKp so it can be used in composition at any depth.
702#[async_trait(?Send)]
703impl<
704    R,
705    Lock,
706    Mid,
707    V,
708    Root,
709    LockValue,
710    MidValue,
711    Value,
712    MutRoot,
713    MutLock,
714    MutMid,
715    MutValue,
716    G1,
717    S1,
718    L,
719    G2,
720    S2,
721> AsyncKeyPathLike<Root, MutRoot>
722    for AsyncLockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
723where
724    Root: std::borrow::Borrow<R>,
725    LockValue: std::borrow::Borrow<Lock>,
726    MidValue: std::borrow::Borrow<Mid>,
727    Value: std::borrow::Borrow<V>,
728    MutRoot: std::borrow::BorrowMut<R>,
729    MutLock: std::borrow::BorrowMut<Lock>,
730    MutMid: std::borrow::BorrowMut<Mid>,
731    MutValue: std::borrow::BorrowMut<V>,
732    G1: Fn(Root) -> Option<LockValue> + Clone,
733    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
734    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
735    G2: Fn(MidValue) -> Option<Value> + Clone,
736    S2: Fn(MutMid) -> Option<MutValue> + Clone,
737    Lock: Clone,
738{
739    type Value = Value;
740    type MutValue = MutValue;
741    async fn get(&self, root: Root) -> Option<Value> {
742        AsyncLockKp::get(self, root).await
743    }
744    async fn get_mut(&self, root: MutRoot) -> Option<MutValue> {
745        AsyncLockKp::get_mut(self, root).await
746    }
747}
748
749/// Chained async lock keypath: two or more async keypaths (Root -> V -> V2 -> ...). Root is passed at get/get_mut time.
750///
751/// Use [AsyncLockKp::then_async] to create (or [ComposedAsyncLockKp::then_async] for more levels). Then call [ComposedAsyncLockKp::get] or
752/// [ComposedAsyncLockKp::get_mut] with root when you need the value.
753///
754/// Chain any depth: `kp1.then_async(kp2).then_async(kp3).then_async(kp4)...` then `.get(&root).await`.
755#[derive(Clone)]
756pub struct ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
757    pub(crate) first: First,
758    pub(crate) second: Second,
759    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
760}
761
762impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
763    ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
764where
765    First: AsyncKeyPathLike<Root, MutRoot>,
766    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
767{
768    /// Get through all chained async locks (root is passed here).
769    pub async fn get(&self, root: Root) -> Option<Value2> {
770        let value = self.first.get(root).await?;
771        self.second.get(value).await
772    }
773
774    /// Get mutable through all composed locks (root is passed here).
775    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
776        let mut_value = self.first.get_mut(root).await?;
777        self.second.get_mut(mut_value).await
778    }
779
780    /// Chain with another async keypath: `a.then_async(b).then_async(c).get(&root).await`.
781    pub fn then_async<
782        Lock3,
783        Mid3,
784        V3,
785        LockValue3,
786        MidValue3,
787        Value3,
788        MutLock3,
789        MutMid3,
790        MutValue3,
791        G3_1,
792        S3_1,
793        L3,
794        G3_2,
795        S3_2,
796    >(
797        self,
798        other: AsyncLockKp<
799            V2,
800            Lock3,
801            Mid3,
802            V3,
803            Value2,
804            LockValue3,
805            MidValue3,
806            Value3,
807            MutValue2,
808            MutLock3,
809            MutMid3,
810            MutValue3,
811            G3_1,
812            S3_1,
813            L3,
814            G3_2,
815            S3_2,
816        >,
817    ) -> ComposedAsyncLockKp<
818        R,
819        V3,
820        Root,
821        Value3,
822        MutRoot,
823        MutValue3,
824        Self,
825        AsyncLockKp<
826            V2,
827            Lock3,
828            Mid3,
829            V3,
830            Value2,
831            LockValue3,
832            MidValue3,
833            Value3,
834            MutValue2,
835            MutLock3,
836            MutMid3,
837            MutValue3,
838            G3_1,
839            S3_1,
840            L3,
841            G3_2,
842            S3_2,
843        >,
844    >
845    where
846        V2: 'static,
847        V3: 'static,
848        Value2: std::borrow::Borrow<V2>,
849        Value3: std::borrow::Borrow<V3>,
850        MutValue2: std::borrow::BorrowMut<V2>,
851        MutValue3: std::borrow::BorrowMut<V3>,
852        LockValue3: std::borrow::Borrow<Lock3>,
853        MidValue3: std::borrow::Borrow<Mid3>,
854        MutLock3: std::borrow::BorrowMut<Lock3>,
855        MutMid3: std::borrow::BorrowMut<Mid3>,
856        G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
857        S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
858        L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
859        G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
860        S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
861        Lock3: Clone,
862    {
863        ComposedAsyncLockKp {
864            first: self,
865            second: other,
866            _p: std::marker::PhantomData,
867        }
868    }
869
870    /// Chain with a regular [crate::Kp] (no root at call site). Use `.get(&root).await` later.
871    pub fn then<V3, Value3, MutValue3, G3, S3>(
872        self,
873        next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
874    ) -> AsyncKeyPathThenKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>>
875    where
876        V2: 'static,
877        V3: 'static,
878        Value2: std::borrow::Borrow<V2>,
879        Value3: std::borrow::Borrow<V3>,
880        MutValue2: std::borrow::BorrowMut<V2>,
881        MutValue3: std::borrow::BorrowMut<V3>,
882        G3: Fn(Value2) -> Option<Value3> + Clone,
883        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
884    {
885        AsyncKeyPathThenKp {
886            first: self,
887            second: next_kp,
888            _p: std::marker::PhantomData,
889        }
890    }
891
892    /// Chain with a sync [crate::lock::LockKp] (no root at call site). Use `.get(&root).await` later.
893    pub fn then_lock<
894        Lock3,
895        Mid3,
896        V3,
897        LockValue3,
898        MidValue3,
899        Value3,
900        MutLock3,
901        MutMid3,
902        MutValue3,
903        G3_1,
904        S3_1,
905        L3,
906        G3_2,
907        S3_2,
908    >(
909        self,
910        lock_kp: crate::lock::LockKp<V2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>,
911    ) -> AsyncLockKpThenLockKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::lock::LockKp<V2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>>
912    where
913        V2: 'static,
914        V3: 'static,
915        Value2: std::borrow::Borrow<V2>,
916        Value3: std::borrow::Borrow<V3>,
917        MutValue2: std::borrow::BorrowMut<V2>,
918        MutValue3: std::borrow::BorrowMut<V3>,
919        LockValue3: std::borrow::Borrow<Lock3>,
920        MidValue3: std::borrow::Borrow<Mid3>,
921        MutLock3: std::borrow::BorrowMut<Lock3>,
922        MutMid3: std::borrow::BorrowMut<Mid3>,
923        G3_1: Fn(Value2) -> Option<LockValue3>,
924        S3_1: Fn(MutValue2) -> Option<MutLock3>,
925        L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
926        G3_2: Fn(MidValue3) -> Option<Value3>,
927        S3_2: Fn(MutMid3) -> Option<MutValue3>,
928    {
929        AsyncLockKpThenLockKp {
930            first: self,
931            second: lock_kp,
932            _p: std::marker::PhantomData,
933        }
934    }
935}
936
937/// Keypath that chains a sync keypath ([crate::Kp]) with an [AsyncKeyPathLike]. Use [crate::Kp::then_async] to create; then `.get(&root).await`.
938#[derive(Clone)]
939pub struct KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second> {
940    pub(crate) first: First,
941    pub(crate) second: Second,
942    pub(crate) _p: std::marker::PhantomData<(R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2)>,
943}
944
945impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
946    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
947where
948    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
949    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
950{
951    /// Get through sync keypath then async keypath (root is passed here).
952    #[inline]
953    pub async fn get(&self, root: Root) -> Option<Value2> {
954        let v = self.first.sync_get(root)?;
955        self.second.get(v).await
956    }
957    /// Get mutable through sync then async (root is passed here).
958    #[inline]
959    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
960        let mut_v = self.first.sync_get_mut(root)?;
961        self.second.get_mut(mut_v).await
962    }
963}
964
965#[async_trait(?Send)]
966impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
967    AsyncKeyPathLike<Root, MutRoot> for KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
968where
969    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
970    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
971{
972    type Value = Value2;
973    type MutValue = MutValue2;
974    async fn get(&self, root: Root) -> Option<Value2> {
975        let v = self.first.sync_get(root)?;
976        self.second.get(v).await
977    }
978    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
979        let mut_v = self.first.sync_get_mut(root)?;
980        self.second.get_mut(mut_v).await
981    }
982}
983
984impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
985    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
986where
987    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
988    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
989{
990    /// Chain with a [crate::Kp]. Use `.get(&root).await` later.
991    pub fn then<V3, Value3, MutValue3, G3, S3>(
992        self,
993        next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
994    ) -> AsyncKeyPathThenKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>>
995    where
996        V3: 'static,
997        Value2: std::borrow::Borrow<V2>,
998        MutValue2: std::borrow::BorrowMut<V2>,
999        Value3: std::borrow::Borrow<V3>,
1000        MutValue3: std::borrow::BorrowMut<V3>,
1001        G3: Fn(Value2) -> Option<Value3> + Clone,
1002        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
1003    {
1004        AsyncKeyPathThenKp {
1005            first: self,
1006            second: next_kp,
1007            _p: std::marker::PhantomData,
1008        }
1009    }
1010}
1011
1012/// Keypath that chains an [AsyncKeyPathLike] (async get) with a [crate::Kp] (sync step). Use `.get(&root).await` to run.
1013#[derive(Clone)]
1014pub struct AsyncKeyPathThenKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
1015    pub(crate) first: First,
1016    pub(crate) second: Second,
1017    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
1018}
1019
1020/// Impl when Second is a Kp whose input type is First::Value (covers both Kp<First::Value, V2, ...> and Kp<RKp, V2, First::Value, ...>).
1021impl<R, V2, Root, Value2, MutRoot, MutValue2, First, RKp, G, S>
1022    AsyncKeyPathThenKp<R, V2, Root, Value2, MutRoot, MutValue2, First, crate::Kp<RKp, V2, First::Value, Value2, First::MutValue, MutValue2, G, S>>
1023where
1024    First: AsyncKeyPathLike<Root, MutRoot>,
1025    First::Value: std::borrow::Borrow<RKp>,
1026    First::MutValue: std::borrow::BorrowMut<RKp>,
1027    Value2: std::borrow::Borrow<V2>,
1028    MutValue2: std::borrow::BorrowMut<V2>,
1029    G: Fn(First::Value) -> Option<Value2>,
1030    S: Fn(First::MutValue) -> Option<MutValue2>,
1031{
1032    /// Get through async keypath then Kp (root is passed here).
1033    #[inline]
1034    pub async fn get(&self, root: Root) -> Option<Value2> {
1035        let value = self.first.get(root).await?;
1036        (self.second.get)(value)
1037    }
1038    /// Get mutable through async keypath then Kp (root is passed here).
1039    #[inline]
1040    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1041        let mut_value = self.first.get_mut(root).await?;
1042        (self.second.set)(mut_value)
1043    }
1044}
1045
1046#[async_trait(?Send)]
1047impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1048    AsyncKeyPathLike<Root, MutRoot> for ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1049where
1050    First: AsyncKeyPathLike<Root, MutRoot>,
1051    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
1052{
1053    type Value = Value2;
1054    type MutValue = MutValue2;
1055    async fn get(&self, root: Root) -> Option<Value2> {
1056        ComposedAsyncLockKp::get(self, root).await
1057    }
1058    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1059        ComposedAsyncLockKp::get_mut(self, root).await
1060    }
1061}
1062
1063// =============================================================================
1064// AsyncLockKpThenLockKp: AsyncLockKp .then_lock(LockKp) — async then sync lock
1065// =============================================================================
1066
1067/// Keypath that goes through an async lock then a sync [crate::lock::LockKp].
1068/// Use [AsyncLockKp::then_lock] to create; then call [AsyncLockKpThenLockKp::get] or [AsyncLockKpThenLockKp::get_mut] with root.
1069#[derive(Clone)]
1070pub struct AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
1071    pub(crate) first: First,
1072    pub(crate) second: Second,
1073    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
1074}
1075
1076impl<
1077        R,
1078        V2,
1079        Root,
1080        Value2,
1081        MutRoot,
1082        MutValue2,
1083        Lock,
1084        Mid,
1085        V,
1086        LockValue,
1087        MidValue,
1088        Value,
1089        MutLock,
1090        MutMid,
1091        MutValue,
1092        G1,
1093        S1,
1094        L,
1095        G2,
1096        S2,
1097        Lock2,
1098        Mid2,
1099        LockValue2,
1100        MidValue2,
1101        MutLock2,
1102        MutMid2,
1103        G2_1,
1104        S2_1,
1105        L2,
1106        G2_2,
1107        S2_2,
1108    >
1109    AsyncLockKpThenLockKp<
1110        R,
1111        V2,
1112        Root,
1113        Value2,
1114        MutRoot,
1115        MutValue2,
1116        AsyncLockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>,
1117        crate::lock::LockKp<V, Lock2, Mid2, V2, Value, LockValue2, MidValue2, Value2, MutValue, MutLock2, MutMid2, MutValue2, G2_1, S2_1, L2, G2_2, S2_2>,
1118    >
1119where
1120    Root: std::borrow::Borrow<R>,
1121    LockValue: std::borrow::Borrow<Lock>,
1122    MidValue: std::borrow::Borrow<Mid>,
1123    Value: std::borrow::Borrow<V>,
1124    MutRoot: std::borrow::BorrowMut<R>,
1125    MutLock: std::borrow::BorrowMut<Lock>,
1126    MutMid: std::borrow::BorrowMut<Mid>,
1127    MutValue: std::borrow::BorrowMut<V>,
1128    Value2: std::borrow::Borrow<V2>,
1129    MutValue2: std::borrow::BorrowMut<V2>,
1130    G1: Fn(Root) -> Option<LockValue> + Clone,
1131    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
1132    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
1133    G2: Fn(MidValue) -> Option<Value> + Clone,
1134    S2: Fn(MutMid) -> Option<MutValue> + Clone,
1135    LockValue2: std::borrow::Borrow<Lock2>,
1136    MidValue2: std::borrow::Borrow<Mid2>,
1137    MutLock2: std::borrow::BorrowMut<Lock2>,
1138    MutMid2: std::borrow::BorrowMut<Mid2>,
1139    G2_1: Fn(Value) -> Option<LockValue2>,
1140    S2_1: Fn(MutValue) -> Option<MutLock2>,
1141    L2: crate::lock::LockAccess<Lock2, MidValue2> + crate::lock::LockAccess<Lock2, MutMid2>,
1142    G2_2: Fn(MidValue2) -> Option<Value2>,
1143    S2_2: Fn(MutMid2) -> Option<MutValue2>,
1144    Lock: Clone,
1145    V: Clone,
1146    V2: Clone,
1147{
1148    /// Get through async lock then sync lock (root is passed here).
1149    pub async fn get(&self, root: Root) -> Option<Value2> {
1150        let value = self.first.get(root).await?;
1151        self.second.get(value)
1152    }
1153
1154    /// Get mutable through async lock then sync lock (root is passed here).
1155    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1156        let mut_value = self.first.get_mut(root).await?;
1157        self.second.get_mut(mut_value)
1158    }
1159}
1160
1161// AsyncLockKpThenLockKp when First is ComposedAsyncLockKp (so ComposedAsyncLockKp::then_lock works).
1162impl<
1163        R,
1164        V2,
1165        Root,
1166        Value2,
1167        MutRoot,
1168        MutValue2,
1169        Lock3,
1170        Mid3,
1171        LockValue3,
1172        MidValue3,
1173        MutLock3,
1174        MutMid3,
1175        G3_1,
1176        S3_1,
1177        L3,
1178        G3_2,
1179        S3_2,
1180        First,
1181        Second,
1182    >
1183    AsyncLockKpThenLockKp<
1184        R,
1185        V2,
1186        Root,
1187        Value2,
1188        MutRoot,
1189        MutValue2,
1190        ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>,
1191        crate::lock::LockKp<Value2, Lock3, Mid3, V2, Value2, LockValue3, MidValue3, Value2, MutValue2, MutLock3, MutMid3, MutValue2, G3_1, S3_1, L3, G3_2, S3_2>,
1192    >
1193where
1194    First: AsyncKeyPathLike<Root, MutRoot>,
1195    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
1196    Value2: std::borrow::Borrow<V2>,
1197    MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
1198    LockValue3: std::borrow::Borrow<Lock3>,
1199    MidValue3: std::borrow::Borrow<Mid3>,
1200    MutLock3: std::borrow::BorrowMut<Lock3>,
1201    MutMid3: std::borrow::BorrowMut<Mid3>,
1202    G3_1: Fn(Value2) -> Option<LockValue3>,
1203    S3_1: Fn(MutValue2) -> Option<MutLock3>,
1204    L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
1205    G3_2: Fn(MidValue3) -> Option<Value2>,
1206    S3_2: Fn(MutMid3) -> Option<MutValue2>,
1207    Value2: Clone,
1208    V2: Clone,
1209{
1210    /// Get through composed async then sync lock (root is passed here).
1211    pub async fn get(&self, root: Root) -> Option<Value2> {
1212        let value = self.first.get(root).await?;
1213        self.second.get(value)
1214    }
1215    /// Get mutable through composed async then sync lock (root is passed here).
1216    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1217        let mut_value = self.first.get_mut(root).await?;
1218        self.second.get_mut(mut_value)
1219    }
1220}
1221
1222// AsyncLockKpThenLockKp when First is AsyncLockKpThenLockKp (nested; enables .then_lock().then_lock() chains).
1223impl<
1224        R,
1225        V2,
1226        Root,
1227        Value2,
1228        MutRoot,
1229        MutValue2,
1230        Lock3,
1231        Mid3,
1232        LockValue3,
1233        MidValue3,
1234        MutLock3,
1235        MutMid3,
1236        G3_1,
1237        S3_1,
1238        L3,
1239        G3_2,
1240        S3_2,
1241        F,
1242        S,
1243    >
1244    AsyncLockKpThenLockKp<
1245        R,
1246        V2,
1247        Root,
1248        Value2,
1249        MutRoot,
1250        MutValue2,
1251        AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, F, S>,
1252        crate::lock::LockKp<Value2, Lock3, Mid3, V2, Value2, LockValue3, MidValue3, Value2, MutValue2, MutLock3, MutMid3, MutValue2, G3_1, S3_1, L3, G3_2, S3_2>,
1253    >
1254where
1255    F: AsyncKeyPathLike<Root, MutRoot, Value = Value2, MutValue = MutValue2>,
1256    S: SyncKeyPathLike<Value2, Value2, MutValue2, MutValue2>,
1257    Value2: std::borrow::Borrow<V2>,
1258    MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
1259    LockValue3: std::borrow::Borrow<Lock3>,
1260    MidValue3: std::borrow::Borrow<Mid3>,
1261    MutLock3: std::borrow::BorrowMut<Lock3>,
1262    MutMid3: std::borrow::BorrowMut<Mid3>,
1263    G3_1: Fn(Value2) -> Option<LockValue3>,
1264    S3_1: Fn(MutValue2) -> Option<MutLock3>,
1265    L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
1266    G3_2: Fn(MidValue3) -> Option<Value2>,
1267    S3_2: Fn(MutMid3) -> Option<MutValue2>,
1268    Value2: Clone,
1269    V2: Clone,
1270{
1271    /// Get through async then sync then sync lock (root is passed here).
1272    pub async fn get(&self, root: Root) -> Option<Value2> {
1273        let value = AsyncKeyPathLike::get(&self.first, root).await?;
1274        self.second.get(value)
1275    }
1276    /// Get mutable through async then sync then sync lock (root is passed here).
1277    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1278        let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
1279        self.second.get_mut(mut_value)
1280    }
1281}
1282
1283// Blanket AsyncKeyPathLike for AsyncLockKpThenLockKp so nested chains (then_lock().then_lock()) work.
1284#[async_trait(?Send)]
1285impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncKeyPathLike<Root, MutRoot>
1286    for AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1287where
1288    First: AsyncKeyPathLike<Root, MutRoot>,
1289    Second: SyncKeyPathLike<First::Value, Value2, First::MutValue, MutValue2>,
1290{
1291    type Value = Value2;
1292    type MutValue = MutValue2;
1293    async fn get(&self, root: Root) -> Option<Value2> {
1294        let value = AsyncKeyPathLike::get(&self.first, root).await?;
1295        SyncKeyPathLike::sync_get(&self.second, value)
1296    }
1297    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1298        let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
1299        SyncKeyPathLike::sync_get_mut(&self.second, mut_value)
1300    }
1301}
1302
1303// then_lock and then on AsyncLockKpThenLockKp so chains can continue.
1304impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1305where
1306    First: AsyncKeyPathLike<Root, MutRoot>,
1307{
1308    /// Chain with an async keypath (e.g. tokio RwLock): ... -> Value2 -> async lock -> Value3.
1309    /// Use `.get(&root).await` or `.get_mut(...).await` on the returned [ComposedAsyncLockKp].
1310    pub fn then_async<
1311        Lock3,
1312        Mid3,
1313        V3,
1314        LockValue3,
1315        MidValue3,
1316        Value3,
1317        MutLock3,
1318        MutMid3,
1319        MutValue3,
1320        G3_1,
1321        S3_1,
1322        L3,
1323        G3_2,
1324        S3_2,
1325    >(
1326        self,
1327        other: AsyncLockKp<
1328            Value2,
1329            Lock3,
1330            Mid3,
1331            V3,
1332            Value2,
1333            LockValue3,
1334            MidValue3,
1335            Value3,
1336            MutValue2,
1337            MutLock3,
1338            MutMid3,
1339            MutValue3,
1340            G3_1,
1341            S3_1,
1342            L3,
1343            G3_2,
1344            S3_2,
1345        >,
1346    ) -> ComposedAsyncLockKp<
1347        Root,
1348        V3,
1349        Root,
1350        Value3,
1351        MutRoot,
1352        MutValue3,
1353        Self,
1354        AsyncLockKp<
1355            Value2,
1356            Lock3,
1357            Mid3,
1358            V3,
1359            Value2,
1360            LockValue3,
1361            MidValue3,
1362            Value3,
1363            MutValue2,
1364            MutLock3,
1365            MutMid3,
1366            MutValue3,
1367            G3_1,
1368            S3_1,
1369            L3,
1370            G3_2,
1371            S3_2,
1372        >,
1373    >
1374    where
1375        V2: 'static,
1376        V3: 'static,
1377        Value2: std::borrow::Borrow<V2>,
1378        Value3: std::borrow::Borrow<V3>,
1379        MutValue2: std::borrow::BorrowMut<V2> + std::borrow::BorrowMut<Value2>,
1380        MutValue3: std::borrow::BorrowMut<V3>,
1381        LockValue3: std::borrow::Borrow<Lock3>,
1382        MidValue3: std::borrow::Borrow<Mid3>,
1383        MutLock3: std::borrow::BorrowMut<Lock3>,
1384        MutMid3: std::borrow::BorrowMut<Mid3>,
1385        G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
1386        S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
1387        L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
1388        G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
1389        S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
1390        Lock3: Clone,
1391    {
1392        ComposedAsyncLockKp {
1393            first: self,
1394            second: other,
1395            _p: std::marker::PhantomData,
1396        }
1397    }
1398
1399    /// Chain with another sync [crate::lock::LockKp]. Use `.get(&root).await` later.
1400    pub fn then_lock<
1401        Lock3,
1402        Mid3,
1403        V3,
1404        LockValue3,
1405        MidValue3,
1406        Value3,
1407        MutLock3,
1408        MutMid3,
1409        MutValue3,
1410        G3_1,
1411        S3_1,
1412        L3,
1413        G3_2,
1414        S3_2,
1415    >(
1416        self,
1417        lock_kp: crate::lock::LockKp<Value2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>,
1418    ) -> AsyncLockKpThenLockKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::lock::LockKp<Value2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>>
1419    where
1420        V3: 'static,
1421        Value2: std::borrow::Borrow<V2>,
1422        Value3: std::borrow::Borrow<V3>,
1423        MutValue2: std::borrow::BorrowMut<Value2>,
1424        MutValue3: std::borrow::BorrowMut<V3>,
1425        LockValue3: std::borrow::Borrow<Lock3>,
1426        MidValue3: std::borrow::Borrow<Mid3>,
1427        MutLock3: std::borrow::BorrowMut<Lock3>,
1428        MutMid3: std::borrow::BorrowMut<Mid3>,
1429        G3_1: Fn(Value2) -> Option<LockValue3>,
1430        S3_1: Fn(MutValue2) -> Option<MutLock3>,
1431        L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
1432        G3_2: Fn(MidValue3) -> Option<Value3>,
1433        S3_2: Fn(MutMid3) -> Option<MutValue3>,
1434    {
1435        AsyncLockKpThenLockKp {
1436            first: self,
1437            second: lock_kp,
1438            _p: std::marker::PhantomData,
1439        }
1440    }
1441
1442    /// Chain with a regular [crate::Kp]. Use `.get(&root).await` later.
1443    pub fn then<V3, Value3, MutValue3, G3, S3>(
1444        self,
1445        next_kp: crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1446    ) -> AsyncKeyPathThenKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>>
1447    where
1448        V3: 'static,
1449        Value2: std::borrow::Borrow<V2>,
1450        Value3: std::borrow::Borrow<V3>,
1451        MutValue2: std::borrow::BorrowMut<Value2>,
1452        MutValue3: std::borrow::BorrowMut<V3>,
1453        G3: Fn(Value2) -> Option<Value3> + Clone,
1454        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
1455    {
1456        AsyncKeyPathThenKp {
1457            first: self,
1458            second: next_kp,
1459            _p: std::marker::PhantomData,
1460        }
1461    }
1462}
1463
1464// ============================================================================
1465// Tokio Mutex Access Implementation
1466// ============================================================================
1467
1468#[cfg(feature = "tokio")]
1469/// Async lock access implementation for Arc<tokio::sync::Mutex<T>>
1470///
1471/// # Cloning Behavior
1472///
1473/// This struct only contains `PhantomData<T>`.
1474/// Cloning is a **zero-cost operation** - no data is copied.
1475#[derive(Clone)] // ZERO-COST: Only clones PhantomData (zero-sized type)
1476pub struct TokioMutexAccess<T> {
1477    _phantom: std::marker::PhantomData<T>,
1478}
1479
1480#[cfg(feature = "tokio")]
1481impl<T> TokioMutexAccess<T> {
1482    pub fn new() -> Self {
1483        Self {
1484            _phantom: std::marker::PhantomData,
1485        }
1486    }
1487}
1488
1489#[cfg(feature = "tokio")]
1490impl<T> Default for TokioMutexAccess<T> {
1491    fn default() -> Self {
1492        Self::new()
1493    }
1494}
1495
1496// Implementation for immutable access
1497#[cfg(feature = "tokio")]
1498#[async_trait]
1499impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::Mutex<T>>, &'a T>
1500    for TokioMutexAccess<T>
1501{
1502    #[inline]
1503    async fn lock_read(&self, lock: &Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
1504        // SHALLOW CLONE: Only Arc refcount is incremented
1505        let guard = lock.lock().await;
1506        let ptr = &*guard as *const T;
1507        unsafe { Some(&*ptr) }
1508    }
1509
1510    #[inline]
1511    async fn lock_write(&self, lock: &mut Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
1512        let guard = lock.lock().await;
1513        let ptr = &*guard as *const T;
1514        unsafe { Some(&*ptr) }
1515    }
1516}
1517
1518// Implementation for mutable access
1519#[cfg(feature = "tokio")]
1520#[async_trait]
1521impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::Mutex<T>>, &'a mut T>
1522    for TokioMutexAccess<T>
1523{
1524    #[inline]
1525    async fn lock_read(&self, lock: &Arc<tokio::sync::Mutex<T>>) -> Option<&'a mut T> {
1526        // SHALLOW CLONE: Only Arc refcount is incremented
1527        let mut guard = lock.lock().await;
1528        let ptr = &mut *guard as *mut T;
1529        unsafe { Some(&mut *ptr) }
1530    }
1531
1532    #[inline]
1533    async fn lock_write(&self, lock: &mut Arc<tokio::sync::Mutex<T>>) -> Option<&'a mut T> {
1534        let mut guard = lock.lock().await;
1535        let ptr = &mut *guard as *mut T;
1536        unsafe { Some(&mut *ptr) }
1537    }
1538}
1539
1540// ============================================================================
1541// Tokio RwLock Access Implementation
1542// ============================================================================
1543
1544#[cfg(feature = "tokio")]
1545/// Async lock access implementation for Arc<tokio::sync::RwLock<T>>
1546///
1547/// # Cloning Behavior
1548///
1549/// This struct only contains `PhantomData<T>`.
1550/// Cloning is a **zero-cost operation** - no data is copied.
1551/// Manual Clone impl so `T: Clone` is not required (e.g. for `Level3` with `RwLock<i32>`).
1552pub struct TokioRwLockAccess<T> {
1553    _phantom: std::marker::PhantomData<T>,
1554}
1555
1556#[cfg(feature = "tokio")]
1557impl<T> TokioRwLockAccess<T> {
1558    pub fn new() -> Self {
1559        Self {
1560            _phantom: std::marker::PhantomData,
1561        }
1562    }
1563}
1564
1565#[cfg(feature = "tokio")]
1566impl<T> Default for TokioRwLockAccess<T> {
1567    fn default() -> Self {
1568        Self::new()
1569    }
1570}
1571
1572#[cfg(feature = "tokio")]
1573impl<T> Clone for TokioRwLockAccess<T> {
1574    fn clone(&self) -> Self {
1575        Self {
1576            _phantom: self._phantom,
1577        }
1578    }
1579}
1580
1581// Implementation for immutable access (read lock)
1582#[cfg(feature = "tokio")]
1583#[async_trait]
1584impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::RwLock<T>>, &'a T>
1585    for TokioRwLockAccess<T>
1586{
1587    async fn lock_read(&self, lock: &Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
1588        // SHALLOW CLONE: Only Arc refcount is incremented
1589        let guard = lock.read().await;
1590        let ptr = &*guard as *const T;
1591        unsafe { Some(&*ptr) }
1592    }
1593
1594    async fn lock_write(&self, lock: &mut Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
1595        // For immutable access, use read lock
1596        let guard = lock.read().await;
1597        let ptr = &*guard as *const T;
1598        unsafe { Some(&*ptr) }
1599    }
1600}
1601
1602// Implementation for mutable access (write lock)
1603#[cfg(feature = "tokio")]
1604#[async_trait]
1605impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::RwLock<T>>, &'a mut T>
1606    for TokioRwLockAccess<T>
1607{
1608    async fn lock_read(&self, lock: &Arc<tokio::sync::RwLock<T>>) -> Option<&'a mut T> {
1609        // For mutable access, use write lock
1610        let mut guard = lock.write().await;
1611        let ptr = &mut *guard as *mut T;
1612        unsafe { Some(&mut *ptr) }
1613    }
1614
1615    async fn lock_write(&self, lock: &mut Arc<tokio::sync::RwLock<T>>) -> Option<&'a mut T> {
1616        // SHALLOW CLONE: Only Arc refcount is incremented
1617        let mut guard = lock.write().await;
1618        let ptr = &mut *guard as *mut T;
1619        unsafe { Some(&mut *ptr) }
1620    }
1621}
1622
1623// ============================================================================
1624// Type aliases for derive macro (return concrete type to avoid lifetime issues)
1625// ============================================================================
1626//
1627// The keypath object is 'static—references are created when get() is called
1628// with a root, not when the keypath is constructed.
1629
1630#[cfg(feature = "tokio")]
1631/// Type alias for AsyncLockKp over Arc<tokio::sync::Mutex<T>>. Use with derive macro's `_async()` methods.
1632pub type AsyncLockKpMutexFor<Root, Lock, Inner> = AsyncLockKp<
1633    Root,
1634    Lock,
1635    Inner,
1636    Inner,
1637    &'static Root,
1638    &'static Lock,
1639    &'static Inner,
1640    &'static Inner,
1641    &'static mut Root,
1642    &'static mut Lock,
1643    &'static mut Inner,
1644    &'static mut Inner,
1645    for<'b> fn(&'b Root) -> Option<&'b Lock>,
1646    for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
1647    TokioMutexAccess<Inner>,
1648    for<'b> fn(&'b Inner) -> Option<&'b Inner>,
1649    for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
1650>;
1651
1652#[cfg(feature = "tokio")]
1653/// Type alias for AsyncLockKp over Arc<tokio::sync::RwLock<T>>. Use with derive macro's `_async()` methods.
1654pub type AsyncLockKpRwLockFor<Root, Lock, Inner> = AsyncLockKp<
1655    Root,
1656    Lock,
1657    Inner,
1658    Inner,
1659    &'static Root,
1660    &'static Lock,
1661    &'static Inner,
1662    &'static Inner,
1663    &'static mut Root,
1664    &'static mut Lock,
1665    &'static mut Inner,
1666    &'static mut Inner,
1667    for<'b> fn(&'b Root) -> Option<&'b Lock>,
1668    for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
1669    TokioRwLockAccess<Inner>,
1670    for<'b> fn(&'b Inner) -> Option<&'b Inner>,
1671    for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
1672>;
1673
1674// ============================================================================
1675// Tests
1676// ============================================================================
1677
1678#[cfg(all(test, feature = "tokio"))]
1679mod tests {
1680    use super::*;
1681    use crate::KpType;
1682
1683    #[tokio::test]
1684    async fn test_async_lock_kp_tokio_mutex_basic() {
1685        use tokio::sync::Mutex;
1686
1687        #[derive(Clone)]
1688        struct Root {
1689            data: Arc<Mutex<String>>,
1690        }
1691
1692        let root = Root {
1693            data: Arc::new(Mutex::new("hello".to_string())),
1694        };
1695
1696        // Create AsyncLockKp
1697        let lock_kp = {
1698            let prev: KpType<Root, Arc<Mutex<String>>> =
1699                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1700            let next: KpType<String, String> =
1701                Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
1702            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1703        };
1704
1705        // Test async get
1706        let value = lock_kp.get(&root).await;
1707        assert!(value.is_some());
1708        assert_eq!(value.unwrap(), &"hello".to_string());
1709    }
1710
1711    #[tokio::test]
1712    async fn test_async_lock_kp_tokio_rwlock_basic() {
1713        use tokio::sync::RwLock;
1714
1715        #[derive(Clone)]
1716        struct Root {
1717            data: Arc<RwLock<Vec<i32>>>,
1718        }
1719
1720        let root = Root {
1721            data: Arc::new(RwLock::new(vec![1, 2, 3, 4, 5])),
1722        };
1723
1724        // Create AsyncLockKp with RwLock
1725        let lock_kp = {
1726            let prev: KpType<Root, Arc<RwLock<Vec<i32>>>> =
1727                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1728            let next: KpType<Vec<i32>, Vec<i32>> =
1729                Kp::new(|v: &Vec<i32>| Some(v), |v: &mut Vec<i32>| Some(v));
1730            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
1731        };
1732
1733        // Test async get with RwLock (read lock)
1734        let value = lock_kp.get(&root).await;
1735        assert!(value.is_some());
1736        assert_eq!(value.unwrap().len(), 5);
1737    }
1738
1739    #[tokio::test]
1740    async fn test_async_lock_kp_concurrent_reads() {
1741        use tokio::sync::RwLock;
1742
1743        #[derive(Clone)]
1744        struct Root {
1745            data: Arc<RwLock<i32>>,
1746        }
1747
1748        let root = Root {
1749            data: Arc::new(RwLock::new(42)),
1750        };
1751
1752        // Create AsyncLockKp
1753        let lock_kp = {
1754            let prev: KpType<Root, Arc<RwLock<i32>>> =
1755                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1756            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1757            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
1758        };
1759
1760        // Spawn multiple concurrent async reads
1761        let mut handles = vec![];
1762        for _ in 0..10 {
1763            let root_clone = root.clone();
1764
1765            // Re-create lock_kp for each task since we can't clone it easily
1766            let lock_kp_for_task = {
1767                let prev: KpType<Root, Arc<RwLock<i32>>> =
1768                    Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1769                let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1770                AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
1771            };
1772
1773            let handle = tokio::spawn(async move { lock_kp_for_task.get(&root_clone).await });
1774            handles.push(handle);
1775        }
1776
1777        // All reads should succeed
1778        for handle in handles {
1779            let result = handle.await.unwrap();
1780            assert_eq!(result, Some(&42));
1781        }
1782
1783        // Test the original lock_kp as well
1784        let value = lock_kp.get(&root).await;
1785        assert_eq!(value, Some(&42));
1786    }
1787
1788    #[tokio::test]
1789    async fn test_async_lock_kp_panic_on_clone_proof() {
1790        use tokio::sync::Mutex;
1791
1792        /// This struct PANICS if cloned - proving no deep cloning occurs
1793        struct PanicOnClone {
1794            data: String,
1795        }
1796
1797        impl Clone for PanicOnClone {
1798            fn clone(&self) -> Self {
1799                panic!("❌ ASYNC DEEP CLONE DETECTED! PanicOnClone was cloned!");
1800            }
1801        }
1802
1803        #[derive(Clone)]
1804        struct Root {
1805            level1: Arc<Mutex<Level1>>,
1806        }
1807
1808        struct Level1 {
1809            panic_data: PanicOnClone,
1810            value: i32,
1811        }
1812
1813        impl Clone for Level1 {
1814            fn clone(&self) -> Self {
1815                panic!("❌ Level1 was deeply cloned in async context!");
1816            }
1817        }
1818
1819        // Create structure with PanicOnClone
1820        let root = Root {
1821            level1: Arc::new(Mutex::new(Level1 {
1822                panic_data: PanicOnClone {
1823                    data: "test".to_string(),
1824                },
1825                value: 123,
1826            })),
1827        };
1828
1829        // Create AsyncLockKp
1830        let lock_kp = {
1831            let prev: KpType<Root, Arc<Mutex<Level1>>> = Kp::new(
1832                |r: &Root| Some(&r.level1),
1833                |r: &mut Root| Some(&mut r.level1),
1834            );
1835            let next: KpType<Level1, i32> = Kp::new(
1836                |l: &Level1| Some(&l.value),
1837                |l: &mut Level1| Some(&mut l.value),
1838            );
1839            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1840        };
1841
1842        // CRITICAL TEST: If any deep cloning occurs, PanicOnClone will trigger
1843        let value = lock_kp.get(&root).await;
1844
1845        // ✅ SUCCESS: No panic means no deep cloning!
1846        assert_eq!(value, Some(&123));
1847    }
1848
1849    #[tokio::test]
1850    async fn test_async_lock_kp_structure() {
1851        use tokio::sync::Mutex;
1852
1853        #[derive(Clone)]
1854        struct Root {
1855            data: Arc<Mutex<String>>,
1856        }
1857
1858        let lock_kp = {
1859            let prev: KpType<Root, Arc<Mutex<String>>> =
1860                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1861            let next: KpType<String, String> =
1862                Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
1863            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1864        };
1865
1866        // Verify structure has three fields (prev, mid, next)
1867        let _ = &lock_kp.prev;
1868        let _ = &lock_kp.mid;
1869        let _ = &lock_kp.next;
1870    }
1871
1872    #[tokio::test]
1873    async fn test_async_kp_then() {
1874        use tokio::sync::Mutex;
1875
1876        #[derive(Clone)]
1877        struct Root {
1878            data: Arc<Mutex<Inner>>,
1879        }
1880
1881        #[derive(Clone)]
1882        struct Inner {
1883            value: i32,
1884        }
1885
1886        let root = Root {
1887            data: Arc::new(Mutex::new(Inner { value: 42 })),
1888        };
1889
1890        // Create AsyncLockKp to Inner
1891        let async_kp = {
1892            let prev: KpType<Root, Arc<Mutex<Inner>>> =
1893                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1894            let next: KpType<Inner, Inner> = Kp::new(|i: &Inner| Some(i), |i: &mut Inner| Some(i));
1895            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1896        };
1897
1898        // Chain with regular Kp to get value field
1899        let value_kp: KpType<Inner, i32> = Kp::new(
1900            |i: &Inner| Some(&i.value),
1901            |i: &mut Inner| Some(&mut i.value),
1902        );
1903
1904        let chained = async_kp.then(value_kp);
1905        let result = chained.get(&root).await;
1906        assert_eq!(result, Some(&42));
1907    }
1908
1909    #[tokio::test]
1910    async fn test_async_kp_later_then() {
1911        use tokio::sync::Mutex;
1912
1913        #[derive(Clone)]
1914        struct Root {
1915            lock1: Arc<Mutex<Container>>,
1916        }
1917
1918        #[derive(Clone)]
1919        struct Container {
1920            lock2: Arc<Mutex<i32>>,
1921        }
1922
1923        let root = Root {
1924            lock1: Arc::new(Mutex::new(Container {
1925                lock2: Arc::new(Mutex::new(999)),
1926            })),
1927        };
1928
1929        // First AsyncLockKp: Root -> Container
1930        let async_kp1 = {
1931            let prev: KpType<Root, Arc<Mutex<Container>>> =
1932                Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
1933            let next: KpType<Container, Container> =
1934                Kp::new(|c: &Container| Some(c), |c: &mut Container| Some(c));
1935            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1936        };
1937
1938        // Second AsyncLockKp: Container -> i32
1939        let async_kp2 = {
1940            let prev: KpType<Container, Arc<Mutex<i32>>> = Kp::new(
1941                |c: &Container| Some(&c.lock2),
1942                |c: &mut Container| Some(&mut c.lock2),
1943            );
1944            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1945            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1946        };
1947
1948        // Chain with then_async; get with root
1949        let chained = async_kp1.then_async(async_kp2);
1950        let result = chained.get(&root).await;
1951        assert_eq!(result, Some(&999));
1952    }
1953
1954    #[tokio::test]
1955    async fn test_async_kp_then_async_three_levels() {
1956        use tokio::sync::Mutex;
1957
1958        #[derive(Clone)]
1959        struct Root {
1960            a: Arc<Mutex<Level1>>,
1961        }
1962        #[derive(Clone)]
1963        struct Level1 {
1964            b: Arc<Mutex<Level2>>,
1965        }
1966        #[derive(Clone)]
1967        struct Level2 {
1968            c: Arc<Mutex<i32>>,
1969        }
1970
1971        let root = Root {
1972            a: Arc::new(Mutex::new(Level1 {
1973                b: Arc::new(Mutex::new(Level2 {
1974                    c: Arc::new(Mutex::new(42)),
1975                })),
1976            })),
1977        };
1978
1979        let kp1 = {
1980            let prev: KpType<Root, Arc<Mutex<Level1>>> =
1981                Kp::new(|r: &Root| Some(&r.a), |r: &mut Root| Some(&mut r.a));
1982            let next: KpType<Level1, Level1> =
1983                Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
1984            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1985        };
1986        let kp2 = {
1987            let prev: KpType<Level1, Arc<Mutex<Level2>>> =
1988                Kp::new(|l: &Level1| Some(&l.b), |l: &mut Level1| Some(&mut l.b));
1989            let next: KpType<Level2, Level2> =
1990                Kp::new(|l: &Level2| Some(l), |l: &mut Level2| Some(l));
1991            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1992        };
1993        let kp3 = {
1994            let prev: KpType<Level2, Arc<Mutex<i32>>> =
1995                Kp::new(|l: &Level2| Some(&l.c), |l: &mut Level2| Some(&mut l.c));
1996            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1997            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1998        };
1999
2000        let chained = kp1.then_async(kp2).then_async(kp3);
2001        let result = chained.get(&root).await;
2002        assert_eq!(result, Some(&42));
2003    }
2004}