Skip to main content

key_paths_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{Data, DeriveInput, Fields, Type, parse_macro_input, spanned::Spanned};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6enum WrapperKind {
7    None,
8    Option,
9    Box,
10    Rc,
11    Arc,
12    Vec,
13    HashMap,
14    BTreeMap,
15    HashSet,
16    BTreeSet,
17    VecDeque,
18    LinkedList,
19    BinaryHeap,
20    // Error handling containers
21    Result,
22    // Reference counting with weak references
23    Weak,
24    // String and owned text
25    String,
26    OptionString,
27    // Interior mutability (std::cell)
28    Cell,
29    RefCell,
30    OptionCell,
31    OptionRefCell,
32    // Lazy init (once_cell, std::sync::OnceLock, std::sync::LazyLock)
33    OnceCell,
34    Lazy,
35    OptionOnceCell,
36    OptionLazy,
37    // Marker / zero-size
38    PhantomData,
39    OptionPhantomData,
40    // Range iterators (std::ops::Range, RangeInclusive)
41    Range,
42    OptionRange,
43    // Nested container support
44    OptionBox,
45    OptionRc,
46    OptionArc,
47    BoxOption,
48    RcOption,
49    ArcOption,
50    VecOption,
51    OptionVec,
52    VecDequeOption,
53    OptionVecDeque,
54    LinkedListOption,
55    OptionLinkedList,
56    BinaryHeapOption,
57    OptionBinaryHeap,
58    HashSetOption,
59    OptionHashSet,
60    BTreeSetOption,
61    OptionBTreeSet,
62    ResultOption,
63    OptionResult,
64    HashMapOption,
65    OptionHashMap,
66    BTreeMapOption,
67    OptionBTreeMap,
68    // Arc with synchronization primitives (default)
69    StdArcMutex,
70    StdArcRwLock,
71    StdArcMutexOption,
72    StdArcRwLockOption,
73    OptionStdArcMutex,
74    OptionStdArcRwLock,
75    // Synchronization primitives default
76    StdMutex,
77    StdRwLock,
78    StdMutexOption,
79    StdRwLockOption,
80    OptionStdMutex,
81    OptionStdRwLock,
82    // Synchronization primitives (parking_lot)
83    Mutex,
84    RwLock,
85    OptionMutex,
86    OptionRwLock,
87    // Synchronization primitives (tokio::sync - requires tokio feature)
88    TokioMutex,
89    TokioRwLock,
90    // parking_lot
91    ArcMutex,
92    ArcRwLock,
93    ArcMutexOption,
94    ArcRwLockOption,
95    OptionArcMutex,
96    OptionArcRwLock,
97    MutexOption,
98    RwLockOption,
99    // Arc with synchronization primitives (tokio::sync - requires tokio feature)
100    TokioArcMutex,
101    TokioArcRwLock,
102    OptionTokioArcMutex,
103    OptionTokioArcRwLock,
104    // Tagged types
105    Tagged,
106    OptionTagged,
107    // Clone-on-write (std::borrow::Cow)
108    Cow,
109    OptionCow,
110    // Reference types (&T, &str, &[T], etc.)
111    Reference,
112    OptionReference,
113    // Atomic types (std::sync::atomic::*)
114    Atomic,
115    OptionAtomic,
116    // Pin types
117    Pin,
118    PinBox,
119    /// Field marked with #[pin] - plain type (pin_project pattern)
120    PinnedField,
121    /// Field marked with #[pin] - Future type (pin_project pattern)
122    PinnedFuture,
123    /// Field marked with #[pin] - Box<dyn Future> (pin_project pattern)
124    PinnedBoxFuture,
125}
126
127/// Helper function to check if a type path is exactly under std::sync (not lock_api or parking_lot).
128/// Requires the path to start with "std" then "sync" so we don't confuse with RwLock&lt;RawRwLock, T&gt; (lock_api).
129fn is_std_sync_type(path: &syn::Path) -> bool {
130    let segments: Vec<_> = path.segments.iter().map(|s| s.ident.to_string()).collect();
131    segments.len() >= 2
132        && segments.get(0).map(|s| s.as_str()) == Some("std")
133        && segments.get(1).map(|s| s.as_str()) == Some("sync")
134}
135
136/// Helper function to check if a type path is exactly under tokio::sync.
137fn is_tokio_sync_type(path: &syn::Path) -> bool {
138    let segments: Vec<_> = path.segments.iter().map(|s| s.ident.to_string()).collect();
139    segments.len() >= 2
140        && segments.get(0).map(|s| s.as_str()) == Some("tokio")
141        && segments.get(1).map(|s| s.as_str()) == Some("sync")
142}
143
144/// Helper function to check if a type path is under parking_lot (RwLock/Mutex from lock_api).
145/// Use so we never treat parking_lot::RwLock as std::sync::RwLock.
146fn is_parking_lot_type(path: &syn::Path) -> bool {
147    path.segments
148        .first()
149        .map(|s| s.ident == "parking_lot")
150        == Some(true)
151}
152
153/// Helper function to check if a type path is under std::sync::atomic (strict prefix).
154fn is_std_sync_atomic_type(path: &syn::Path) -> bool {
155    let segments: Vec<_> = path.segments.iter().map(|s| s.ident.to_string()).collect();
156    segments.len() >= 3
157        && segments.get(0).map(|s| s.as_str()) == Some("std")
158        && segments.get(1).map(|s| s.as_str()) == Some("sync")
159        && segments.get(2).map(|s| s.as_str()) == Some("atomic")
160}
161
162/// Atomic type idents (no type params): AtomicBool, AtomicI8, etc.
163const ATOMIC_TYPE_IDENTS: &[&str] = &[
164    "AtomicBool", "AtomicI8", "AtomicI16", "AtomicI32", "AtomicI64", "AtomicI128", "AtomicIsize",
165    "AtomicU8", "AtomicU16", "AtomicU32", "AtomicU64", "AtomicU128", "AtomicUsize",
166];
167
168fn extract_wrapper_inner_type(ty: &Type) -> (WrapperKind, Option<Type>) {
169    use syn::{GenericArgument, PathArguments};
170
171    // Handle reference types: &T, &'a str, &[T], etc.
172    if let Type::Reference(tr) = ty {
173        return (WrapperKind::Reference, Some((*tr.elem).clone()));
174    }
175
176    if let Type::Path(tp) = ty {
177        // Check if this is explicitly a std::sync type
178        let is_std_sync = is_std_sync_type(&tp.path);
179        // Check if this is explicitly a tokio::sync type
180        let is_tokio_sync = is_tokio_sync_type(&tp.path);
181
182        if let Some(seg) = tp.path.segments.last() {
183            let ident_str = seg.ident.to_string();
184
185            if let PathArguments::AngleBracketed(ab) = &seg.arguments {
186                let args: Vec<_> = ab.args.iter().collect();
187
188                // Handle map types (HashMap, BTreeMap) - they have K, V parameters
189                if ident_str == "HashMap" || ident_str == "BTreeMap" {
190                    if let (Some(_key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
191                        if let GenericArgument::Type(inner) = value_arg {
192                            // Check for nested Option in map values
193                            let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
194                            match (ident_str.as_str(), inner_kind) {
195                                ("HashMap", WrapperKind::Option) => {
196                                    return (WrapperKind::HashMapOption, inner_inner);
197                                }
198                                ("BTreeMap", WrapperKind::Option) => {
199                                    return (WrapperKind::BTreeMapOption, inner_inner);
200                                }
201                                _ => {
202                                    return match ident_str.as_str() {
203                                        "HashMap" => (WrapperKind::HashMap, Some(inner.clone())),
204                                        "BTreeMap" => (WrapperKind::BTreeMap, Some(inner.clone())),
205                                        _ => (WrapperKind::None, None),
206                                    };
207                                }
208                            }
209                        }
210                    }
211                }
212                // Handle Cow<'a, B> - has lifetime then type parameter
213                else if ident_str == "Cow" {
214                    if let Some(inner) = args.iter().find_map(|arg| {
215                        if let GenericArgument::Type(t) = arg {
216                            Some(t.clone())
217                        } else {
218                            None
219                        }
220                    }) {
221                        return (WrapperKind::Cow, Some(inner));
222                    }
223                }
224                // Handle single-parameter container types
225                else if let Some(arg) = args.get(0) {
226                    if let GenericArgument::Type(inner) = arg {
227                        // Check for nested containers first
228                        let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
229
230                        // Handle nested combinations
231                        match (ident_str.as_str(), inner_kind) {
232                            ("Option", WrapperKind::Box) => {
233                                return (WrapperKind::OptionBox, inner_inner);
234                            }
235                            ("Option", WrapperKind::Rc) => {
236                                return (WrapperKind::OptionRc, inner_inner);
237                            }
238                            ("Option", WrapperKind::Arc) => {
239                                return (WrapperKind::OptionArc, inner_inner);
240                            }
241                            ("Option", WrapperKind::Vec) => {
242                                return (WrapperKind::OptionVec, inner_inner);
243                            }
244                            ("Option", WrapperKind::HashMap) => {
245                                return (WrapperKind::OptionHashMap, inner_inner);
246                            }
247                            ("Option", WrapperKind::BTreeMap) => {
248                                return (WrapperKind::OptionBTreeMap, inner_inner);
249                            }
250                            ("Option", WrapperKind::VecDeque) => {
251                                return (WrapperKind::OptionVecDeque, inner_inner);
252                            }
253                            ("Option", WrapperKind::LinkedList) => {
254                                return (WrapperKind::OptionLinkedList, inner_inner);
255                            }
256                            ("Option", WrapperKind::BinaryHeap) => {
257                                return (WrapperKind::OptionBinaryHeap, inner_inner);
258                            }
259                            ("Option", WrapperKind::HashSet) => {
260                                return (WrapperKind::OptionHashSet, inner_inner);
261                            }
262                            ("Option", WrapperKind::BTreeSet) => {
263                                return (WrapperKind::OptionBTreeSet, inner_inner);
264                            }
265                            ("Option", WrapperKind::Result) => {
266                                return (WrapperKind::OptionResult, inner_inner);
267                            }
268                            ("Option", WrapperKind::StdArcMutex) => {
269                                return (WrapperKind::OptionStdArcMutex, inner_inner);
270                            }
271                            ("Option", WrapperKind::StdArcRwLock) => {
272                                return (WrapperKind::OptionStdArcRwLock, inner_inner);
273                            }
274                            ("Option", WrapperKind::ArcMutex) => {
275                                return (WrapperKind::OptionArcMutex, inner_inner);
276                            }
277                            ("Option", WrapperKind::ArcRwLock) => {
278                                return (WrapperKind::OptionArcRwLock, inner_inner);
279                            }
280                            ("Option", WrapperKind::StdMutex) => {
281                                return (WrapperKind::OptionStdMutex, inner_inner);
282                            }
283                            ("Option", WrapperKind::StdRwLock) => {
284                                return (WrapperKind::OptionStdRwLock, inner_inner);
285                            }
286                            ("Option", WrapperKind::Mutex) => {
287                                return (WrapperKind::OptionMutex, inner_inner);
288                            }
289                            ("Option", WrapperKind::RwLock) => {
290                                return (WrapperKind::OptionRwLock, inner_inner);
291                            }
292                            ("Option", WrapperKind::TokioArcMutex) => {
293                                return (WrapperKind::OptionTokioArcMutex, inner_inner);
294                            }
295                            ("Option", WrapperKind::TokioArcRwLock) => {
296                                return (WrapperKind::OptionTokioArcRwLock, inner_inner);
297                            }
298                            ("Option", WrapperKind::Cow) => {
299                                return (WrapperKind::OptionCow, inner_inner);
300                            }
301                            ("Option", WrapperKind::Tagged) => {
302                                return (WrapperKind::OptionTagged, inner_inner);
303                            }
304                            ("Option", WrapperKind::Reference) => {
305                                return (WrapperKind::OptionReference, Some(inner.clone()));
306                            }
307                            ("Option", WrapperKind::Atomic) => {
308                                return (WrapperKind::OptionAtomic, Some(inner.clone()));
309                            }
310                            ("Option", WrapperKind::String) => {
311                                return (WrapperKind::OptionString, None);
312                            }
313                            ("Option", WrapperKind::Cell) => {
314                                return (WrapperKind::OptionCell, inner_inner);
315                            }
316                            ("Option", WrapperKind::RefCell) => {
317                                return (WrapperKind::OptionRefCell, inner_inner);
318                            }
319                            ("Option", WrapperKind::OnceCell) => {
320                                return (WrapperKind::OptionOnceCell, inner_inner);
321                            }
322                            ("Option", WrapperKind::Lazy) => {
323                                return (WrapperKind::OptionLazy, inner_inner);
324                            }
325                            ("Option", WrapperKind::PhantomData) => {
326                                return (WrapperKind::OptionPhantomData, inner_inner);
327                            }
328                            ("Option", WrapperKind::Range) => {
329                                return (WrapperKind::OptionRange, inner_inner);
330                            }
331                            ("Pin", WrapperKind::Box) => {
332                                return (WrapperKind::PinBox, inner_inner);
333                            }
334                            ("Box", WrapperKind::Option) => {
335                                return (WrapperKind::BoxOption, inner_inner);
336                            }
337                            ("Rc", WrapperKind::Option) => {
338                                return (WrapperKind::RcOption, inner_inner);
339                            }
340                            ("Arc", WrapperKind::Option) => {
341                                return (WrapperKind::ArcOption, inner_inner);
342                            }
343                            ("Vec", WrapperKind::Option) => {
344                                return (WrapperKind::VecOption, inner_inner);
345                            }
346                            ("VecDeque", WrapperKind::Option) => {
347                                return (WrapperKind::VecDequeOption, inner_inner);
348                            }
349                            ("LinkedList", WrapperKind::Option) => {
350                                return (WrapperKind::LinkedListOption, inner_inner);
351                            }
352                            ("BinaryHeap", WrapperKind::Option) => {
353                                return (WrapperKind::BinaryHeapOption, inner_inner);
354                            }
355                            ("HashSet", WrapperKind::Option) => {
356                                return (WrapperKind::HashSetOption, inner_inner);
357                            }
358                            ("BTreeSet", WrapperKind::Option) => {
359                                return (WrapperKind::BTreeSetOption, inner_inner);
360                            }
361                            ("Result", WrapperKind::Option) => {
362                                return (WrapperKind::ResultOption, inner_inner);
363                            }
364                            ("HashMap", WrapperKind::Option) => {
365                                return (WrapperKind::HashMapOption, inner_inner);
366                            }
367                            // BTreeMapOption is handled in the map block (HashMap/BTreeMap)
368                            // Mutex<Option<T>> / RwLock<Option<T>> (yields LockKp value T)
369                            // std::sync::Mutex<Option<T>> / RwLock<Option<T>>
370                            ("Mutex", WrapperKind::Option) if is_std_sync_type(&tp.path) => {
371                                return (WrapperKind::StdMutexOption, inner_inner);
372                            }
373                            ("RwLock", WrapperKind::Option) if is_std_sync_type(&tp.path) => {
374                                return (WrapperKind::StdRwLockOption, inner_inner);
375                            }
376                            // parking_lot::Mutex<Option<T>> / RwLock<Option<T>>, and bare Mutex/RwLock assumed parking_lot
377                            ("Mutex", WrapperKind::Option) => {
378                                return (WrapperKind::MutexOption, inner_inner);
379                            }
380                            ("RwLock", WrapperKind::Option) => {
381                                return (WrapperKind::RwLockOption, inner_inner);
382                            }
383                            // std::sync variants (when inner is StdMutex/StdRwLock)
384                            ("Arc", WrapperKind::StdMutex) => {
385                                return (WrapperKind::StdArcMutex, inner_inner);
386                            }
387                            ("Arc", WrapperKind::StdRwLock) => {
388                                return (WrapperKind::StdArcRwLock, inner_inner);
389                            }
390                            ("Arc", WrapperKind::StdMutexOption) => {
391                                return (WrapperKind::StdArcMutexOption, inner_inner);
392                            }
393                            ("Arc", WrapperKind::StdRwLockOption) => {
394                                return (WrapperKind::StdArcRwLockOption, inner_inner);
395                            }
396                            // parking_lot variants (default - when inner is Mutex/RwLock without std::sync prefix)
397                            ("Arc", WrapperKind::Mutex) => {
398                                return (WrapperKind::ArcMutex, inner_inner);
399                            }
400                            ("Arc", WrapperKind::RwLock) => {
401                                return (WrapperKind::ArcRwLock, inner_inner);
402                            }
403                            ("Arc", WrapperKind::MutexOption) => {
404                                return (WrapperKind::ArcMutexOption, inner_inner);
405                            }
406                            ("Arc", WrapperKind::RwLockOption) => {
407                                return (WrapperKind::ArcRwLockOption, inner_inner);
408                            }
409                            // tokio::sync variants (when inner is TokioMutex/TokioRwLock)
410                            ("Arc", WrapperKind::TokioMutex) => {
411                                return (WrapperKind::TokioArcMutex, inner_inner);
412                            }
413                            ("Arc", WrapperKind::TokioRwLock) => {
414                                return (WrapperKind::TokioArcRwLock, inner_inner);
415                            }
416                            _ => {
417                                // Handle single-level containers
418                                // For Mutex and RwLock:
419                                // - If path contains std::sync, it's std::sync (StdMutex/StdRwLock)
420                                // - Otherwise, default to parking_lot (Mutex/RwLock)
421                                return match ident_str.as_str() {
422                                    "Option" => (WrapperKind::Option, Some(inner.clone())),
423                                    "Box" => (WrapperKind::Box, Some(inner.clone())),
424                                    "Rc" => (WrapperKind::Rc, Some(inner.clone())),
425                                    "Arc" => (WrapperKind::Arc, Some(inner.clone())),
426                                    "Vec" => (WrapperKind::Vec, Some(inner.clone())),
427                                    "HashSet" => (WrapperKind::HashSet, Some(inner.clone())),
428                                    "BTreeSet" => (WrapperKind::BTreeSet, Some(inner.clone())),
429                                    "VecDeque" => (WrapperKind::VecDeque, Some(inner.clone())),
430                                    "LinkedList" => (WrapperKind::LinkedList, Some(inner.clone())),
431                                    "BinaryHeap" => (WrapperKind::BinaryHeap, Some(inner.clone())),
432                                    "Result" => (WrapperKind::Result, Some(inner.clone())),
433                                    // Explicit parking_lot path (lock_api::RwLock) — never treat as std
434                                    "Mutex" if is_parking_lot_type(&tp.path) => {
435                                        (WrapperKind::Mutex, Some(inner.clone()))
436                                    }
437                                    "RwLock" if is_parking_lot_type(&tp.path) => {
438                                        (WrapperKind::RwLock, Some(inner.clone()))
439                                    }
440                                    // std::sync::Mutex and std::sync::RwLock only when path starts with std::sync
441                                    "Mutex" if is_std_sync => {
442                                        (WrapperKind::StdMutex, Some(inner.clone()))
443                                    }
444                                    "RwLock" if is_std_sync => {
445                                        (WrapperKind::StdRwLock, Some(inner.clone()))
446                                    }
447                                    // tokio::sync::Mutex and tokio::sync::RwLock
448                                    "Mutex" if is_tokio_sync => {
449                                        (WrapperKind::TokioMutex, Some(inner.clone()))
450                                    }
451                                    "RwLock" if is_tokio_sync => {
452                                        (WrapperKind::TokioRwLock, Some(inner.clone()))
453                                    }
454                                    // Default: parking_lot (bare Mutex/RwLock or unknown path)
455                                    "Mutex" => (WrapperKind::Mutex, Some(inner.clone())),
456                                    "RwLock" => (WrapperKind::RwLock, Some(inner.clone())),
457                                    "Weak" => (WrapperKind::Weak, Some(inner.clone())),
458                                    "Tagged" => (WrapperKind::Tagged, Some(inner.clone())),
459                                    "Cow" => (WrapperKind::Cow, Some(inner.clone())),
460                                    "AtomicPtr" if is_std_sync_atomic_type(&tp.path) => (WrapperKind::Atomic, None),
461                                    "Pin" => (WrapperKind::Pin, Some(inner.clone())),
462                                    "Cell" => (WrapperKind::Cell, Some(inner.clone())),
463                                    "RefCell" => (WrapperKind::RefCell, Some(inner.clone())),
464                                    "OnceCell" | "OnceLock" => (WrapperKind::OnceCell, Some(inner.clone())),
465                                    "Lazy" | "LazyLock" => (WrapperKind::Lazy, Some(inner.clone())),
466                                    "PhantomData" => (WrapperKind::PhantomData, Some(inner.clone())),
467                                    "Range" | "RangeInclusive" => (WrapperKind::Range, Some(inner.clone())),
468                                    _ => (WrapperKind::None, None),
469                                };
470                            }
471                        }
472                    }
473                }
474            }
475            // Handle atomic types with no angle bracket args (AtomicBool, AtomicI32, etc.)
476            if matches!(seg.arguments, PathArguments::None) {
477                if ident_str == "String" {
478                    return (WrapperKind::String, None);
479                }
480                if is_std_sync_atomic_type(&tp.path)
481                    && ATOMIC_TYPE_IDENTS.contains(&ident_str.as_str())
482                {
483                    return (WrapperKind::Atomic, None);
484                }
485            }
486        }
487    }
488    (WrapperKind::None, None)
489}
490
491/// Check if a field has the #[pin] attribute (pin_project pattern).
492fn field_has_pin_attr(field: &syn::Field) -> bool {
493    field.attrs.iter().any(|attr| {
494        attr.path().get_ident().map(|i| i == "pin").unwrap_or(false)
495    })
496}
497
498/// Check if a type is a Future (dyn Future, impl Future, or Box<dyn Future>).
499fn is_future_type(ty: &Type) -> bool {
500    use syn::{GenericArgument, PathArguments, TypeParamBound};
501
502    match ty {
503        Type::TraitObject(trait_obj) => trait_obj.bounds.iter().any(|b| {
504            if let TypeParamBound::Trait(t) = b {
505                t.path.segments.last()
506                    .map(|s| s.ident == "Future")
507                    .unwrap_or(false)
508            } else {
509                false
510            }
511        }),
512        Type::ImplTrait(impl_trait) => impl_trait.bounds.iter().any(|b| {
513            if let TypeParamBound::Trait(t) = b {
514                t.path.segments.last()
515                    .map(|s| s.ident == "Future")
516                    .unwrap_or(false)
517            } else {
518                false
519            }
520        }),
521        Type::Path(tp) => {
522            if let Some(seg) = tp.path.segments.last() {
523                match seg.ident.to_string().as_str() {
524                    "Box" | "Pin" => {
525                        if let PathArguments::AngleBracketed(args) = &seg.arguments {
526                            if let Some(GenericArgument::Type(inner)) = args.args.first() {
527                                return is_future_type(inner);
528                            }
529                        }
530                    }
531                    _ => {}
532                }
533            }
534            false
535        }
536        _ => false,
537    }
538}
539
540/// Extract Output type from Future trait bound (dyn Future<Output = T>, impl Future<Output = T>, etc.).
541fn extract_future_output(ty: &Type) -> Option<Type> {
542    use syn::{GenericArgument, PathArguments, TypeParamBound};
543
544    let bounds = match ty {
545        Type::TraitObject(t) => &t.bounds,
546        Type::ImplTrait(t) => &t.bounds,
547        Type::Path(tp) => {
548            if let Some(seg) = tp.path.segments.last() {
549                if matches!(seg.ident.to_string().as_str(), "Box" | "Pin") {
550                    if let PathArguments::AngleBracketed(args) = &seg.arguments {
551                        if let Some(GenericArgument::Type(inner)) = args.args.first() {
552                            return extract_future_output(inner);
553                        }
554                    }
555                }
556            }
557            return None;
558        }
559        _ => return None,
560    };
561
562    for bound in bounds {
563        if let TypeParamBound::Trait(trait_bound) = bound {
564            if let Some(seg) = trait_bound.path.segments.last() {
565                if seg.ident == "Future" {
566                    if let PathArguments::AngleBracketed(args) = &seg.arguments {
567                        for arg in &args.args {
568                            if let GenericArgument::AssocType(assoc) = arg {
569                                if assoc.ident == "Output" {
570                                    return Some(assoc.ty.clone());
571                                }
572                            }
573                        }
574                    }
575                }
576            }
577        }
578    }
579    None
580}
581
582/// For HashMap<K,V> or BTreeMap<K,V>, returns Some((key_ty, value_ty)).
583fn extract_map_key_value(ty: &Type) -> Option<(Type, Type)> {
584    use syn::{GenericArgument, PathArguments};
585
586    if let Type::Path(tp) = ty {
587        if let Some(seg) = tp.path.segments.last() {
588            let ident_str = seg.ident.to_string();
589            if ident_str == "HashMap" || ident_str == "BTreeMap" {
590                if let PathArguments::AngleBracketed(ab) = &seg.arguments {
591                    let args: Vec<_> = ab.args.iter().collect();
592                    if let (Some(key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
593                        if let (GenericArgument::Type(key_ty), GenericArgument::Type(value_ty)) =
594                            (key_arg, value_arg)
595                        {
596                            return Some((key_ty.clone(), value_ty.clone()));
597                        }
598                    }
599                }
600            }
601        }
602    }
603    None
604}
605
606fn to_snake_case(name: &str) -> String {
607    let mut out = String::new();
608    for (i, c) in name.chars().enumerate() {
609        if c.is_uppercase() {
610            if i != 0 {
611                out.push('_');
612            }
613            out.push(c.to_ascii_lowercase());
614        } else {
615            out.push(c);
616        }
617    }
618    out
619}
620
621/// Derive macro for generating simple keypath methods.
622/// 
623/// Generates one method per field: `StructName::field_name()` that returns a `Kp`.
624/// Intelligently handles wrapper types (Option, Vec, Box, Arc, etc.) to generate appropriate keypaths.
625/// 
626/// # Example
627/// 
628/// ```ignore
629/// #[derive(Kp)]
630/// struct Person {
631///     name: String,
632///     age: i32,
633///     email: Option<String>,
634///     addresses: Vec<String>,
635/// }
636/// 
637/// // Generates:
638/// // impl Person {
639/// //     pub fn name() -> Kp<...> { ... }
640/// //     pub fn age() -> Kp<...> { ... }
641/// //     pub fn email() -> Kp<...> { ... } // unwraps Option
642/// //     pub fn addresses() -> Kp<...> { ... } // accesses first element
643/// // }
644/// ```
645#[proc_macro_derive(Kp)]
646pub fn derive_keypaths(input: TokenStream) -> TokenStream {
647    let input = parse_macro_input!(input as DeriveInput);
648    let name = &input.ident;
649    let input_span = input.span();
650
651    let methods = match input.data {
652        Data::Struct(data_struct) => match data_struct.fields {
653            Fields::Named(fields_named) => {
654                let mut tokens = proc_macro2::TokenStream::new();
655
656                // Generate identity methods for the struct
657                tokens.extend(quote! {
658                    /// Returns a generic identity keypath for this type
659                    #[inline(always)]
660                    pub fn _identity<Root, MutRoot>() -> rust_key_paths::Kp<
661                        #name,
662                        #name,
663                        Root,
664                        Root,
665                        MutRoot,
666                        MutRoot,
667                        fn(Root) -> Option<Root>,
668                        fn(MutRoot) -> Option<MutRoot>,
669                    >
670                    where
671                        Root: std::borrow::Borrow<#name>,
672                        MutRoot: std::borrow::BorrowMut<#name>,
673                    {
674                        rust_key_paths::Kp::new(
675                            |r: Root| Some(r),
676                            |r: MutRoot| Some(r)
677                        )
678                    }
679
680                    // /// Returns a simple identity keypath for this type
681                    // #[inline(always)]
682                    // pub fn identity() -> rust_key_paths::KpType<'static, #name, #name> {
683                    //     rust_key_paths::Kp::new(
684                    //         |r: &#name| Some(r),
685                    //         |r: &mut #name| Some(r)
686                    //     )
687                    // }
688                });
689                
690                // When struct has #[pin] fields, generated code calls this.project() which must
691                // be provided by #[pin_project]. If missing, user gets: no method named `project`.
692
693                for field in fields_named.named.iter() {
694                    let field_ident = field.ident.as_ref().unwrap();
695                    let ty = &field.ty;
696                    // Centralized keypath method names – change here to adjust for all types
697                    let kp_fn = format_ident!("{}", field_ident);
698                    let kp_at_fn = format_ident!("{}_at", field_ident);
699
700                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
701
702                    // Override kind when field has #[pin] (pin_project pattern)
703                    let (kind, inner_ty) = if field_has_pin_attr(field) {
704                        let pinned_kind = if let Some(output_ty) = extract_future_output(ty) {
705                            if matches!(kind, WrapperKind::Box) {
706                                (WrapperKind::PinnedBoxFuture, Some(output_ty))
707                            } else {
708                                (WrapperKind::PinnedFuture, Some(output_ty))
709                            }
710                        } else if is_future_type(ty) {
711                            (WrapperKind::PinnedFuture, inner_ty.clone())
712                        } else {
713                            (WrapperKind::PinnedField, inner_ty.clone())
714                        };
715                        pinned_kind
716                    } else {
717                        (kind, inner_ty.clone())
718                    };
719
720                    match (kind, inner_ty) {
721                        (WrapperKind::Option, Some(inner_ty)) => {
722                            // For Option<T>, unwrap and access inner type
723                            tokens.extend(quote! {
724                                #[inline(always)]
725                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
726                                    rust_key_paths::Kp::new(
727                                        |root: &#name| root.#field_ident.as_ref(),
728                                        |root: &mut #name| root.#field_ident.as_mut(),
729                                    )
730                                }
731                            });
732                        }
733                        (WrapperKind::OptionBox, Some(inner_ty)) => {
734                            // For Option<Box<T>>, keypath to T: get returns Option<&T> via as_deref()
735                            tokens.extend(quote! {
736                                #[inline(always)]
737                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
738                                    rust_key_paths::Kp::new(
739                                        |root: &#name| root.#field_ident.as_deref(),
740                                        |root: &mut #name| root.#field_ident.as_deref_mut(),
741                                    )
742                                }
743                            });
744                        }
745                        (WrapperKind::OptionRc, Some(inner_ty)) => {
746                            // For Option<Rc<T>>, keypath to T: get returns Option<&T> via as_deref()
747                            // Setter: as_mut() gives Option<&mut Rc<T>>, and_then(Rc::get_mut) gives Option<&mut T>
748                            tokens.extend(quote! {
749                                #[inline(always)]
750                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
751                                    rust_key_paths::Kp::new(
752                                        |root: &#name| root.#field_ident.as_deref(),
753                                        |root: &mut #name| root.#field_ident.as_mut().and_then(std::rc::Rc::get_mut),
754                                    )
755                                }
756                            });
757                        }
758                        (WrapperKind::OptionArc, Some(inner_ty)) => {
759                            // For Option<Arc<T>>, keypath to T: get returns Option<&T> via as_deref()
760                            // Setter: as_mut() gives Option<&mut Arc<T>>, and_then(Arc::get_mut) gives Option<&mut T>
761                            tokens.extend(quote! {
762                                #[inline(always)]
763                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
764                                    rust_key_paths::Kp::new(
765                                        |root: &#name| root.#field_ident.as_deref(),
766                                        |root: &mut #name| root.#field_ident.as_mut().and_then(std::sync::Arc::get_mut),
767                                    )
768                                }
769                            });
770                        }
771                        (WrapperKind::OptionVecDeque, Some(_inner_ty))
772                        | (WrapperKind::OptionLinkedList, Some(_inner_ty))
773                        | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
774                        | (WrapperKind::OptionHashSet, Some(_inner_ty))
775                        | (WrapperKind::OptionBTreeSet, Some(_inner_ty))
776                        | (WrapperKind::OptionResult, Some(_inner_ty))
777                        | (WrapperKind::OptionBTreeMap, Some(_inner_ty)) => {
778                            // Keypath to the Option container (reference), like Vec/HashSet
779                            tokens.extend(quote! {
780                                #[inline(always)]
781                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
782                                    rust_key_paths::Kp::new(
783                                        |root: &#name| Some(&root.#field_ident),
784                                        |root: &mut #name| Some(&mut root.#field_ident),
785                                    )
786                                }
787                            });
788                        }
789                        (WrapperKind::Vec, Some(inner_ty)) => {
790                            tokens.extend(quote! {
791                                #[inline(always)]
792                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
793                                    rust_key_paths::Kp::new(
794                                        |root: &#name| Some(&root.#field_ident),
795                                        |root: &mut #name| Some(&mut root.#field_ident),
796                                    )
797                                }
798                                #[inline(always)]
799                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
800                                    rust_key_paths::Kp::new(
801                                        Box::new(move |root: &#name| root.#field_ident.get(index)),
802                                        Box::new(move |root: &mut #name| root.#field_ident.get_mut(index)),
803                                    )
804                                }
805                            });
806                        }
807                        (WrapperKind::HashMap, Some(inner_ty)) => {
808                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
809                                tokens.extend(quote! {
810                                    #[inline(always)]
811                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
812                                        rust_key_paths::Kp::new(
813                                            |root: &#name| Some(&root.#field_ident),
814                                            |root: &mut #name| Some(&mut root.#field_ident),
815                                        )
816                                    }
817                                    #[inline(always)]
818                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
819                                    where
820                                        #key_ty: Clone + std::hash::Hash + Eq + 'static,
821                                    {
822                                        let key2 = key.clone();
823                                        rust_key_paths::Kp::new(
824                                            Box::new(move |root: &#name| root.#field_ident.get(&key)),
825                                            Box::new(move |root: &mut #name| root.#field_ident.get_mut(&key2)),
826                                        )
827                                    }
828                                });
829                            } else {
830                                tokens.extend(quote! {
831                                    #[inline(always)]
832                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
833                                        rust_key_paths::Kp::new(
834                                            |root: &#name| Some(&root.#field_ident),
835                                            |root: &mut #name| Some(&mut root.#field_ident),
836                                        )
837                                    }
838                                });
839                            }
840                        }
841                        (WrapperKind::BTreeMap, Some(inner_ty)) | (WrapperKind::BTreeMapOption, Some(inner_ty)) => {
842                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
843                                tokens.extend(quote! {
844                                    #[inline(always)]
845                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
846                                        rust_key_paths::Kp::new(
847                                            |root: &#name| Some(&root.#field_ident),
848                                            |root: &mut #name| Some(&mut root.#field_ident),
849                                        )
850                                    }
851                                    #[inline(always)]
852                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
853                                    where
854                                        #key_ty: Clone + Ord + 'static,
855                                    {
856                                        let key2 = key.clone();
857                                        rust_key_paths::Kp::new(
858                                            Box::new(move |root: &#name| root.#field_ident.get(&key)),
859                                            Box::new(move |root: &mut #name| root.#field_ident.get_mut(&key2)),
860                                        )
861                                    }
862                                });
863                            } else {
864                                tokens.extend(quote! {
865                                    #[inline(always)]
866                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
867                                        rust_key_paths::Kp::new(
868                                            |root: &#name| Some(&root.#field_ident),
869                                            |root: &mut #name| Some(&mut root.#field_ident),
870                                        )
871                                    }
872                                });
873                            }
874                        }
875                        (WrapperKind::Box, Some(inner_ty)) => {
876                            // For Box<T>, deref to inner type (returns &T / &mut T, not &Box<T>)
877                            tokens.extend(quote! {
878                                #[inline(always)]
879                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
880                                    rust_key_paths::Kp::new(
881                                        |root: &#name| Some(&*root.#field_ident),
882                                        |root: &mut #name| Some(&mut *root.#field_ident),
883                                    )
884                                }
885                            });
886                        }
887                        (WrapperKind::BoxOption, Some(inner_ty)) => {
888                            // For Box<Option<T>>, keypath to T: deref Box to Option<T>, then Option::as_ref/as_mut
889                            tokens.extend(quote! {
890                                #[inline(always)]
891                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
892                                    rust_key_paths::Kp::new(
893                                        |root: &#name| (&*root.#field_ident).as_ref(),
894                                        |root: &mut #name| (&mut *root.#field_ident).as_mut(),
895                                    )
896                                }
897                            });
898                        }
899                        (WrapperKind::RcOption, Some(inner_ty)) => {
900                            // For Rc<Option<T>>, keypath to T: deref Rc to &Option<T>, then Option::as_ref; set = Rc::get_mut then as_mut
901                            tokens.extend(quote! {
902                                #[inline(always)]
903                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
904                                    rust_key_paths::Kp::new(
905                                        |root: &#name| (&*root.#field_ident).as_ref(),
906                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#field_ident).and_then(std::option::Option::as_mut),
907                                    )
908                                }
909                            });
910                        }
911                        (WrapperKind::ArcOption, Some(inner_ty)) => {
912                            // For Arc<Option<T>>, keypath to T: deref Arc to &Option<T>, then Option::as_ref; set = Arc::get_mut then as_mut
913                            tokens.extend(quote! {
914                                #[inline(always)]
915                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
916                                    rust_key_paths::Kp::new(
917                                        |root: &#name| (&*root.#field_ident).as_ref(),
918                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#field_ident).and_then(std::option::Option::as_mut),
919                                    )
920                                }
921                            });
922                        }
923                        (WrapperKind::Pin, Some(inner_ty)) => {
924                            let kp_inner_fn = format_ident!("{}_inner", field_ident);
925                            tokens.extend(quote! {
926                                #[inline(always)]
927                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
928                                    rust_key_paths::Kp::new(
929                                        |root: &#name| Some(&root.#field_ident),
930                                        |root: &mut #name| Some(&mut root.#field_ident),
931                                    )
932                                }
933                                #[inline(always)]
934                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
935                                where #inner_ty: std::marker::Unpin
936                                {
937                                    rust_key_paths::Kp::new(
938                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#field_ident).get_ref()),
939                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#field_ident).get_mut()),
940                                    )
941                                }
942                            });
943                        }
944                        (WrapperKind::PinBox, Some(inner_ty)) => {
945                            let kp_inner_fn = format_ident!("{}_inner", field_ident);
946                            tokens.extend(quote! {
947                                #[inline(always)]
948                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
949                                    rust_key_paths::Kp::new(
950                                        |root: &#name| Some(&root.#field_ident),
951                                        |root: &mut #name| Some(&mut root.#field_ident),
952                                    )
953                                }
954                                #[inline(always)]
955                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
956                                where #inner_ty: std::marker::Unpin
957                                {
958                                    // Pin::as_ref on Pin<Box<T>> returns Pin<&T> (Box Deref target), so get_ref() already gives &T
959                                    rust_key_paths::Kp::new(
960                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#field_ident).get_ref()),
961                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#field_ident).get_mut()),
962                                    )
963                                }
964                            });
965                        }
966                        (WrapperKind::PinnedField, _) => {
967                            let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
968                            tokens.extend(quote! {
969                                #[inline(always)]
970                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
971                                    rust_key_paths::Kp::new(
972                                        |root: &#name| Some(&root.#field_ident),
973                                        |root: &mut #name| Some(&mut root.#field_ident),
974                                    )
975                                }
976                                /// Pinned projection for #[pin] field. Requires #[pin_project] on struct.
977                                #[inline(always)]
978                                pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
979                                    this.project().#field_ident
980                                }
981                            });
982                        }
983                        (WrapperKind::PinnedFuture, _) => {
984                            let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
985                            let kp_await_fn = format_ident!("{}_await", field_ident);
986                            let kp_pin_future_fn = format_ident!("{}_pin_future_kp", field_ident);
987                            let output_ty = quote! { <#ty as std::future::Future>::Output };
988                            tokens.extend(quote! {
989                                #[inline(always)]
990                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
991                                    rust_key_paths::Kp::new(
992                                        |root: &#name| Some(&root.#field_ident),
993                                        |root: &mut #name| Some(&mut root.#field_ident),
994                                    )
995                                }
996                                /// Pinned projection for #[pin] Future field. Requires #[pin_project] on struct.
997                                #[inline(always)]
998                                pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
999                                    this.project().#field_ident
1000                                }
1001                                /// Poll the pinned future. Requires #[pin_project] on struct.
1002                                pub async fn #kp_await_fn(this: std::pin::Pin<&mut #name>) -> Option<#output_ty>
1003                                where #ty: std::future::Future
1004                                {
1005                                    use std::future::Future;
1006                                    Some(this.project().#field_ident.await)
1007                                }
1008                                /// Keypath for [rust_key_paths::Kp::then_pin_future]. Composable pin future await.
1009                                #[inline(always)]
1010                                pub fn #kp_pin_future_fn() -> impl rust_key_paths::pin::PinFutureAwaitLike<#name, #output_ty> {
1011                                    rust_key_paths::pin_future_await_kp!(#name, #kp_await_fn -> #output_ty)
1012                                }
1013                            });
1014                        }
1015                        (WrapperKind::PinnedBoxFuture, Some(output_ty)) => {
1016                            let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
1017                            let kp_await_fn = format_ident!("{}_await", field_ident);
1018                            let kp_pin_future_fn = format_ident!("{}_pin_future_kp", field_ident);
1019                            tokens.extend(quote! {
1020                                #[inline(always)]
1021                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1022                                    rust_key_paths::Kp::new(
1023                                        |root: &#name| Some(&root.#field_ident),
1024                                        |root: &mut #name| Some(&mut root.#field_ident),
1025                                    )
1026                                }
1027                                /// Pinned projection for #[pin] Box<dyn Future> field. Requires #[pin_project] on struct.
1028                                #[inline(always)]
1029                                pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
1030                                    this.project().#field_ident
1031                                }
1032                                /// Poll the pinned boxed future. Requires #[pin_project] on struct.
1033                                pub async fn #kp_await_fn(this: std::pin::Pin<&mut #name>) -> Option<#output_ty> {
1034                                    Some(this.project().#field_ident.await)
1035                                }
1036                                /// Keypath for [rust_key_paths::Kp::then_pin_future]. Composable pin future await.
1037                                #[inline(always)]
1038                                pub fn #kp_pin_future_fn() -> impl rust_key_paths::pin::PinFutureAwaitLike<#name, #output_ty> {
1039                                    rust_key_paths::pin_future_await_kp!(#name, #kp_await_fn -> #output_ty)
1040                                }
1041                            });
1042                        }
1043                        (WrapperKind::Rc, Some(inner_ty)) => {
1044                            // For Rc<T>, deref to inner type (returns &T; get_mut when uniquely owned)
1045                            tokens.extend(quote! {
1046                                #[inline(always)]
1047                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1048                                    rust_key_paths::Kp::new(
1049                                        |root: &#name| Some(root.#field_ident.as_ref()),
1050                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#field_ident),
1051                                    )
1052                                }
1053                            });
1054                        }
1055                        (WrapperKind::Arc, Some(inner_ty)) => {
1056                            // For Arc<T>, deref to inner type (returns &T; get_mut when uniquely owned)
1057                            tokens.extend(quote! {
1058                                #[inline(always)]
1059                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1060                                    rust_key_paths::Kp::new(
1061                                        |root: &#name| Some(root.#field_ident.as_ref()),
1062                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#field_ident),
1063                                    )
1064                                }
1065                            });
1066                        }
1067                        (WrapperKind::Cow, Some(inner_ty)) => {
1068                            // For Cow<'_, B>, deref to inner type (as_ref/to_mut)
1069                            tokens.extend(quote! {
1070                                #[inline(always)]
1071                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1072                                    rust_key_paths::Kp::new(
1073                                        |root: &#name| Some(root.#field_ident.as_ref()),
1074                                        |root: &mut #name| Some(root.#field_ident.to_mut()),
1075                                    )
1076                                }
1077                            });
1078                        }
1079                        
1080                        (WrapperKind::OptionCow, Some(inner_ty)) => {
1081                            // For Option<Cow<'_, B>>
1082                            tokens.extend(quote! {
1083                                #[inline(always)]
1084                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1085                                    rust_key_paths::Kp::new(
1086                                        |root: &#name| root.#field_ident.as_ref().map(|c| c.as_ref()),
1087                                        |root: &mut #name| root.#field_ident.as_mut().map(|c| c.to_mut()),
1088                                    )
1089                                }
1090                            });
1091                        }
1092                        (WrapperKind::OptionTagged, Some(inner_ty)) => {
1093                            // For Option<Tagged<Tag, T>> - Tagged implements Deref/DerefMut
1094                            tokens.extend(quote! {
1095                                #[inline(always)]
1096                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1097                                    rust_key_paths::Kp::new(
1098                                        |root: &#name| root.#field_ident.as_ref().map(|t| std::ops::Deref::deref(t)),
1099                                        |root: &mut #name| root.#field_ident.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
1100                                    )
1101                                }
1102                            });
1103                        }
1104                        (WrapperKind::OptionReference, Some(inner_ty)) => {
1105                            // For Option<&T>, Option<&str>, Option<&[T]> - read-only, setter returns None
1106                            tokens.extend(quote! {
1107                                #[inline(always)]
1108                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1109                                    rust_key_paths::Kp::new(
1110                                        |root: &#name| root.#field_ident.as_ref(),
1111                                        |_root: &mut #name| None,
1112                                    )
1113                                }
1114                            });
1115                        }
1116                        (WrapperKind::HashSet, Some(inner_ty)) | (WrapperKind::HashSetOption, Some(inner_ty)) => {
1117                            let kp_at_fn = format_ident!("{}_at", field_ident);
1118
1119                            tokens.extend(quote! {
1120                                #[inline(always)]
1121                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1122                                    rust_key_paths::Kp::new(
1123                                        |root: &#name| Some(&root.#field_ident),
1124                                        |root: &mut #name| Some(&mut root.#field_ident),
1125                                    )
1126                                }
1127
1128                                /// _at: check if element exists and get reference.
1129                                /// HashSet does not allow mutable element access (would break hash invariant).
1130                                #[inline(always)]
1131                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1132                                where
1133                                    #inner_ty: Clone + std::hash::Hash + Eq + 'static,
1134                                {
1135                                    rust_key_paths::Kp::new(
1136                                        Box::new(move |root: &#name| root.#field_ident.get(&key)),
1137                                        Box::new(move |_root: &mut #name| None),
1138                                    )
1139                                }
1140                            });
1141                        }
1142                        (WrapperKind::BTreeSet, Some(inner_ty)) | (WrapperKind::BTreeSetOption, Some(inner_ty)) => {
1143                            let kp_at_fn = format_ident!("{}_at", field_ident);
1144
1145                            tokens.extend(quote! {
1146                                #[inline(always)]
1147                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1148                                    rust_key_paths::Kp::new(
1149                                        |root: &#name| Some(&root.#field_ident),
1150                                        |root: &mut #name| Some(&mut root.#field_ident),
1151                                    )
1152                                }
1153
1154                                /// _at: check if element exists and get reference.
1155                                /// BTreeSet does not allow mutable element access (would break ordering invariant).
1156                                #[inline(always)]
1157                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1158                                where
1159                                    #inner_ty: Clone + Ord + 'static,
1160                                {
1161                                    rust_key_paths::Kp::new(
1162                                        Box::new(move |root: &#name| root.#field_ident.get(&key)),
1163                                        Box::new(move |_root: &mut #name| None),
1164                                    )
1165                                }
1166                            });
1167                        }
1168                        (WrapperKind::VecDeque, Some(inner_ty)) | (WrapperKind::VecDequeOption, Some(inner_ty)) => {
1169                            tokens.extend(quote! {
1170                                #[inline(always)]
1171                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1172                                    rust_key_paths::Kp::new(
1173                                        |root: &#name| Some(&root.#field_ident),
1174                                        |root: &mut #name| Some(&mut root.#field_ident),
1175                                    )
1176                                }
1177                                #[inline(always)]
1178                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
1179                                    rust_key_paths::Kp::new(
1180                                        Box::new(move |root: &#name| root.#field_ident.get(index)),
1181                                        Box::new(move |root: &mut #name| root.#field_ident.get_mut(index)),
1182                                    )
1183                                }
1184                            });
1185                        }
1186                        (WrapperKind::LinkedList, Some(_inner_ty)) | (WrapperKind::LinkedListOption, Some(_inner_ty)) => {
1187                            tokens.extend(quote! {
1188                                #[inline(always)]
1189                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1190                                    rust_key_paths::Kp::new(
1191                                        |root: &#name| Some(&root.#field_ident),
1192                                        |root: &mut #name| Some(&mut root.#field_ident),
1193                                    )
1194                                }
1195                            });
1196                        }
1197                        (WrapperKind::BinaryHeap, Some(_inner_ty)) | (WrapperKind::BinaryHeapOption, Some(_inner_ty)) => {
1198                            tokens.extend(quote! {
1199                                #[inline(always)]
1200                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1201                                    rust_key_paths::Kp::new(
1202                                        |root: &#name| Some(&root.#field_ident),
1203                                        |root: &mut #name| Some(&mut root.#field_ident),
1204                                    )
1205                                }
1206                            });
1207                        }
1208                        (WrapperKind::Result, Some(inner_ty)) => {
1209                            // For Result<T, E>, access Ok value
1210                            tokens.extend(quote! {
1211                                #[inline(always)]
1212                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1213                                    rust_key_paths::Kp::new(
1214                                        |root: &#name| root.#field_ident.as_ref().ok(),
1215                                        |root: &mut #name| root.#field_ident.as_mut().ok(),
1216                                    )
1217                                }
1218                            });
1219                        }
1220                        (WrapperKind::StdArcMutex, Some(inner_ty)) => {
1221                            // For Arc<std::sync::Mutex<T>>
1222                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1223                            tokens.extend(quote! {
1224                                #[inline(always)]
1225                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1226                                    rust_key_paths::Kp::new(
1227                                        |root: &#name| Some(&root.#field_ident),
1228                                        |root: &mut #name| Some(&mut root.#field_ident),
1229                                    )
1230                                }
1231                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcMutexFor<#name, #ty, #inner_ty> {
1232                                    rust_key_paths::lock::LockKp::new(
1233                                        rust_key_paths::Kp::new(
1234                                            |root: &#name| Some(&root.#field_ident),
1235                                            |root: &mut #name| Some(&mut root.#field_ident),
1236                                        ),
1237                                        rust_key_paths::lock::ArcMutexAccess::new(),
1238                                        rust_key_paths::Kp::new(
1239                                            |v: &#inner_ty| Some(v),
1240                                            |v: &mut #inner_ty| Some(v),
1241                                        ),
1242                                    )
1243                                }
1244                            });
1245                        }
1246                        (WrapperKind::StdArcRwLock, Some(inner_ty)) => {
1247                            // For Arc<std::sync::RwLock<T>>
1248                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1249                            tokens.extend(quote! {
1250                                #[inline(always)]
1251                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1252                                    rust_key_paths::Kp::new(
1253                                        |root: &#name| Some(&root.#field_ident),
1254                                        |root: &mut #name| Some(&mut root.#field_ident),
1255                                    )
1256                                }
1257                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, #ty, #inner_ty> {
1258                                    rust_key_paths::lock::LockKp::new(
1259                                        rust_key_paths::Kp::new(
1260                                            |root: &#name| Some(&root.#field_ident),
1261                                            |root: &mut #name| Some(&mut root.#field_ident),
1262                                        ),
1263                                        rust_key_paths::lock::ArcRwLockAccess::new(),
1264                                        rust_key_paths::Kp::new(
1265                                            |v: &#inner_ty| Some(v),
1266                                            |v: &mut #inner_ty| Some(v),
1267                                        ),
1268                                    )
1269                                }
1270                            });
1271                        }
1272                        (WrapperKind::StdArcMutexOption, Some(inner_ty)) => {
1273                            // For Arc<std::sync::Mutex<Option<T>>> — LockKp value T (extract from Option); guard gives &Option<T>
1274                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1275                            tokens.extend(quote! {
1276                                #[inline(always)]
1277                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1278                                    rust_key_paths::Kp::new(
1279                                        |root: &#name| Some(&root.#field_ident),
1280                                        |root: &mut #name| Some(&mut root.#field_ident),
1281                                    )
1282                                }
1283                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcMutexOptionFor<#name, #ty, #inner_ty> {
1284                                    rust_key_paths::lock::LockKp::new(
1285                                        rust_key_paths::Kp::new(
1286                                            |root: &#name| Some(&root.#field_ident),
1287                                            |root: &mut #name| Some(&mut root.#field_ident),
1288                                        ),
1289                                        rust_key_paths::lock::ArcMutexAccess::<Option<#inner_ty>>::new(),
1290                                        rust_key_paths::Kp::new(
1291                                            Option::<#inner_ty>::as_ref,
1292                                            Option::<#inner_ty>::as_mut,
1293                                        ),
1294                                    )
1295                                }
1296                            });
1297                        }
1298                        (WrapperKind::StdArcRwLockOption, Some(inner_ty)) => {
1299                            // For Arc<std::sync::RwLock<Option<T>>> — LockKp value T (extract from Option); guard gives &Option<T>
1300                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1301                            tokens.extend(quote! {
1302                                #[inline(always)]
1303                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1304                                    rust_key_paths::Kp::new(
1305                                        |root: &#name| Some(&root.#field_ident),
1306                                        |root: &mut #name| Some(&mut root.#field_ident),
1307                                    )
1308                                }
1309                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcRwLockOptionFor<#name, #ty, #inner_ty> {
1310                                    rust_key_paths::lock::LockKp::new(
1311                                        rust_key_paths::Kp::new(
1312                                            |root: &#name| Some(&root.#field_ident),
1313                                            |root: &mut #name| Some(&mut root.#field_ident),
1314                                        ),
1315                                        rust_key_paths::lock::ArcRwLockAccess::<Option<#inner_ty>>::new(),
1316                                        rust_key_paths::Kp::new(
1317                                            Option::<#inner_ty>::as_ref,
1318                                            Option::<#inner_ty>::as_mut,
1319                                        ),
1320                                    )
1321                                }
1322                            });
1323                        }
1324                        (WrapperKind::ArcRwLock, Some(inner_ty)) => {
1325                            // For Arc<parking_lot::RwLock<T>> (requires rust-key-paths "parking_lot" feature)
1326                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1327                            tokens.extend(quote! {
1328                                #[inline(always)]
1329                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1330                                    rust_key_paths::Kp::new(
1331                                        |root: &#name| Some(&root.#field_ident),
1332                                        |root: &mut #name| Some(&mut root.#field_ident),
1333                                    )
1334                                }
1335                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, #ty, #inner_ty> {
1336                                    rust_key_paths::lock::LockKp::new(
1337                                        rust_key_paths::Kp::new(
1338                                            |root: &#name| Some(&root.#field_ident),
1339                                            |root: &mut #name| Some(&mut root.#field_ident),
1340                                        ),
1341                                        rust_key_paths::lock::ParkingLotRwLockAccess::new(),
1342                                        rust_key_paths::Kp::new(
1343                                            |v: &#inner_ty| Some(v),
1344                                            |v: &mut #inner_ty| Some(v),
1345                                        ),
1346                                    )
1347                                }
1348                            });
1349                        }
1350                        (WrapperKind::ArcMutex, Some(inner_ty)) => {
1351                            // For Arc<parking_lot::Mutex<T>> (requires rust-key-paths "parking_lot" feature)
1352                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1353                            tokens.extend(quote! {
1354                                #[inline(always)]
1355                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1356                                    rust_key_paths::Kp::new(
1357                                        |root: &#name| Some(&root.#field_ident),
1358                                        |root: &mut #name| Some(&mut root.#field_ident),
1359                                    )
1360                                }
1361                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, #ty, #inner_ty> {
1362                                    rust_key_paths::lock::LockKp::new(
1363                                        rust_key_paths::Kp::new(
1364                                            |root: &#name| Some(&root.#field_ident),
1365                                            |root: &mut #name| Some(&mut root.#field_ident),
1366                                        ),
1367                                        rust_key_paths::lock::ParkingLotMutexAccess::new(),
1368                                        rust_key_paths::Kp::new(
1369                                            |v: &#inner_ty| Some(v),
1370                                            |v: &mut #inner_ty| Some(v),
1371                                        ),
1372                                    )
1373                                }
1374                            });
1375                        }
1376                        (WrapperKind::ArcMutexOption, Some(inner_ty)) => {
1377                            // For Arc<parking_lot::Mutex<Option<T>>> — LockKp value T (extract from Option); guard gives &Option<T>
1378                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1379                            tokens.extend(quote! {
1380                                #[inline(always)]
1381                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1382                                    rust_key_paths::Kp::new(
1383                                        |root: &#name| Some(&root.#field_ident),
1384                                        |root: &mut #name| Some(&mut root.#field_ident),
1385                                    )
1386                                }
1387                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotMutexOptionFor<#name, #ty, #inner_ty> {
1388                                    rust_key_paths::lock::LockKp::new(
1389                                        rust_key_paths::Kp::new(
1390                                            |root: &#name| Some(&root.#field_ident),
1391                                            |root: &mut #name| Some(&mut root.#field_ident),
1392                                        ),
1393                                        rust_key_paths::lock::ParkingLotMutexAccess::<Option<#inner_ty>>::new(),
1394                                        rust_key_paths::Kp::new(
1395                                            Option::<#inner_ty>::as_ref,
1396                                            Option::<#inner_ty>::as_mut,
1397                                        ),
1398                                    )
1399                                }
1400                            });
1401                        }
1402                        (WrapperKind::ArcRwLockOption, Some(inner_ty)) => {
1403                            // For Arc<parking_lot::RwLock<Option<T>>> — LockKp value T (extract from Option); guard gives &Option<T>
1404                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1405                            tokens.extend(quote! {
1406                                #[inline(always)]
1407                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1408                                    rust_key_paths::Kp::new(
1409                                        |root: &#name| Some(&root.#field_ident),
1410                                        |root: &mut #name| Some(&mut root.#field_ident),
1411                                    )
1412                                }
1413                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotRwLockOptionFor<#name, #ty, #inner_ty> {
1414                                    rust_key_paths::lock::LockKp::new(
1415                                        rust_key_paths::Kp::new(
1416                                            |root: &#name| Some(&root.#field_ident),
1417                                            |root: &mut #name| Some(&mut root.#field_ident),
1418                                        ),
1419                                        rust_key_paths::lock::ParkingLotRwLockAccess::<Option<#inner_ty>>::new(),
1420                                        rust_key_paths::Kp::new(
1421                                            Option::<#inner_ty>::as_ref,
1422                                            Option::<#inner_ty>::as_mut,
1423                                        ),
1424                                    )
1425                                }
1426                            });
1427                        }
1428                        (WrapperKind::Mutex, Some(_inner_ty))
1429                        | (WrapperKind::StdMutex, Some(_inner_ty)) => {
1430                            // For Mutex<T>, return keypath to container
1431                            tokens.extend(quote! {
1432                                #[inline(always)]
1433                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1434                                    rust_key_paths::Kp::new(
1435                                        |root: &#name| Some(&root.#field_ident),
1436                                        |root: &mut #name| Some(&mut root.#field_ident),
1437                                    )
1438                                }
1439                            });
1440                        }
1441                        (WrapperKind::RwLock, Some(_inner_ty))
1442                        | (WrapperKind::StdRwLock, Some(_inner_ty)) => {
1443                            // For RwLock<T>, return keypath to container
1444                            tokens.extend(quote! {
1445                                #[inline(always)]
1446                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1447                                    rust_key_paths::Kp::new(
1448                                        |root: &#name| Some(&root.#field_ident),
1449                                        |root: &mut #name| Some(&mut root.#field_ident),
1450                                    )
1451                                }
1452                            });
1453                        }
1454                        (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
1455                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1456                            tokens.extend(quote! {
1457                                #[inline(always)]
1458                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1459                                    rust_key_paths::Kp::new(
1460                                        |root: &#name| Some(&root.#field_ident),
1461                                        |root: &mut #name| Some(&mut root.#field_ident),
1462                                    )
1463                                }
1464                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #ty, #inner_ty> {
1465                                    rust_key_paths::async_lock::AsyncLockKp::new(
1466                                        rust_key_paths::Kp::new(
1467                                            |root: &#name| Some(&root.#field_ident),
1468                                            |root: &mut #name| Some(&mut root.#field_ident),
1469                                        ),
1470                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
1471                                        rust_key_paths::Kp::new(
1472                                            |v: &#inner_ty| Some(v),
1473                                            |v: &mut #inner_ty| Some(v),
1474                                        ),
1475                                    )
1476                                }
1477                            });
1478                        }
1479                        (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
1480                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1481                            tokens.extend(quote! {
1482                                #[inline(always)]
1483                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1484                                    rust_key_paths::Kp::new(
1485                                        |root: &#name| Some(&root.#field_ident),
1486                                        |root: &mut #name| Some(&mut root.#field_ident),
1487                                    )
1488                                }
1489                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #ty, #inner_ty> {
1490                                    rust_key_paths::async_lock::AsyncLockKp::new(
1491                                        rust_key_paths::Kp::new(
1492                                            |root: &#name| Some(&root.#field_ident),
1493                                            |root: &mut #name| Some(&mut root.#field_ident),
1494                                        ),
1495                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
1496                                        rust_key_paths::Kp::new(
1497                                            |v: &#inner_ty| Some(v),
1498                                            |v: &mut #inner_ty| Some(v),
1499                                        ),
1500                                    )
1501                                }
1502                            });
1503                        }
1504                        (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
1505                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1506                            tokens.extend(quote! {
1507                                #[inline(always)]
1508                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1509                                    rust_key_paths::Kp::new(
1510                                        |root: &#name| Some(&root.#field_ident),
1511                                        |root: &mut #name| Some(&mut root.#field_ident),
1512                                    )
1513                                }
1514                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
1515                                    rust_key_paths::async_lock::AsyncLockKp::new(
1516                                        rust_key_paths::Kp::new(
1517                                            |root: &#name| root.#field_ident.as_ref(),
1518                                            |root: &mut #name| root.#field_ident.as_mut(),
1519                                        ),
1520                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
1521                                        rust_key_paths::Kp::new(
1522                                            |v: &#inner_ty| Some(v),
1523                                            |v: &mut #inner_ty| Some(v),
1524                                        ),
1525                                    )
1526                                }
1527                            });
1528                        }
1529                        (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
1530                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1531                            tokens.extend(quote! {
1532                                #[inline(always)]
1533                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1534                                    rust_key_paths::Kp::new(
1535                                        |root: &#name| Some(&root.#field_ident),
1536                                        |root: &mut #name| Some(&mut root.#field_ident),
1537                                    )
1538                                }
1539                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
1540                                    rust_key_paths::async_lock::AsyncLockKp::new(
1541                                        rust_key_paths::Kp::new(
1542                                            |root: &#name| root.#field_ident.as_ref(),
1543                                            |root: &mut #name| root.#field_ident.as_mut(),
1544                                        ),
1545                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
1546                                        rust_key_paths::Kp::new(
1547                                            |v: &#inner_ty| Some(v),
1548                                            |v: &mut #inner_ty| Some(v),
1549                                        ),
1550                                    )
1551                                }
1552                            });
1553                        }
1554                        (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
1555                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1556                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1557                            tokens.extend(quote! {
1558                                #[inline(always)]
1559                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1560                                    rust_key_paths::Kp::new(
1561                                        |root: &#name| Some(&root.#field_ident),
1562                                        |root: &mut #name| Some(&mut root.#field_ident),
1563                                    )
1564                                }
1565                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::Mutex<#inner_ty>>> {
1566                                //     rust_key_paths::Kp::new(
1567                                //         |root: &#name| root.#field_ident.as_ref(),
1568                                //         |root: &mut #name| root.#field_ident.as_mut(),
1569                                //     )
1570                                // }
1571                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcMutexFor<#name, std::sync::Arc<std::sync::Mutex<#inner_ty>>, #inner_ty> {
1572                                    rust_key_paths::lock::LockKp::new(
1573                                        rust_key_paths::Kp::new(
1574                                            |root: &#name| root.#field_ident.as_ref(),
1575                                            |root: &mut #name| root.#field_ident.as_mut(),
1576                                        ),
1577                                        rust_key_paths::lock::ArcMutexAccess::new(),
1578                                        rust_key_paths::Kp::new(
1579                                            |v: &#inner_ty| Some(v),
1580                                            |v: &mut #inner_ty| Some(v),
1581                                        ),
1582                                    )
1583                                }
1584                            });
1585                        }
1586                        (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
1587                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1588                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1589                            tokens.extend(quote! {
1590                                #[inline(always)]
1591                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1592                                    rust_key_paths::Kp::new(
1593                                        |root: &#name| Some(&root.#field_ident),
1594                                        |root: &mut #name| Some(&mut root.#field_ident),
1595                                    )
1596                                }
1597                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>> {
1598                                //     rust_key_paths::Kp::new(
1599                                //         |root: &#name| root.#field_ident.as_ref(),
1600                                //         |root: &mut #name| root.#field_ident.as_mut(),
1601                                //     )
1602                                // }
1603                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>, #inner_ty> {
1604                                    rust_key_paths::lock::LockKp::new(
1605                                        rust_key_paths::Kp::new(
1606                                            |root: &#name| root.#field_ident.as_ref(),
1607                                            |root: &mut #name| root.#field_ident.as_mut(),
1608                                        ),
1609                                        rust_key_paths::lock::ParkingLotMutexAccess::new(),
1610                                        rust_key_paths::Kp::new(
1611                                            |v: &#inner_ty| Some(v),
1612                                            |v: &mut #inner_ty| Some(v),
1613                                        ),
1614                                    )
1615                                }
1616                            });
1617                        }
1618                        (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
1619                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1620                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1621                            tokens.extend(quote! {
1622                                #[inline(always)]
1623                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1624                                    rust_key_paths::Kp::new(
1625                                        |root: &#name| Some(&root.#field_ident),
1626                                        |root: &mut #name| Some(&mut root.#field_ident),
1627                                    )
1628                                }
1629                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::RwLock<#inner_ty>>> {
1630                                //     rust_key_paths::Kp::new(
1631                                //         |root: &#name| root.#field_ident.as_ref(),
1632                                //         |root: &mut #name| root.#field_ident.as_mut(),
1633                                //     )
1634                                // }
1635                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, std::sync::Arc<std::sync::RwLock<#inner_ty>>, #inner_ty> {
1636                                    rust_key_paths::lock::LockKp::new(
1637                                        rust_key_paths::Kp::new(
1638                                            |root: &#name| root.#field_ident.as_ref(),
1639                                            |root: &mut #name| root.#field_ident.as_mut(),
1640                                        ),
1641                                        rust_key_paths::lock::ArcRwLockAccess::new(),
1642                                        rust_key_paths::Kp::new(
1643                                            |v: &#inner_ty| Some(v),
1644                                            |v: &mut #inner_ty| Some(v),
1645                                        ),
1646                                    )
1647                                }
1648                            });
1649                        }
1650                        (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
1651                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1652                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1653                            tokens.extend(quote! {
1654                                #[inline(always)]
1655                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1656                                    rust_key_paths::Kp::new(
1657                                        |root: &#name| Some(&root.#field_ident),
1658                                        |root: &mut #name| Some(&mut root.#field_ident),
1659                                    )
1660                                }
1661                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>> {
1662                                //     rust_key_paths::Kp::new(
1663                                //         |root: &#name| root.#field_ident.as_ref(),
1664                                //         |root: &mut #name| root.#field_ident.as_mut(),
1665                                //     )
1666                                // }
1667                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>, #inner_ty> {
1668                                    rust_key_paths::lock::LockKp::new(
1669                                        rust_key_paths::Kp::new(
1670                                            |root: &#name| root.#field_ident.as_ref(),
1671                                            |root: &mut #name| root.#field_ident.as_mut(),
1672                                        ),
1673                                        rust_key_paths::lock::ParkingLotRwLockAccess::new(),
1674                                        rust_key_paths::Kp::new(
1675                                            |v: &#inner_ty| Some(v),
1676                                            |v: &mut #inner_ty| Some(v),
1677                                        ),
1678                                    )
1679                                }
1680                            });
1681                        }
1682                        (WrapperKind::OptionStdMutex, Some(inner_ty)) => {
1683                            let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1684                            tokens.extend(quote! {
1685                                #[inline(always)]
1686                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1687                                    rust_key_paths::Kp::new(
1688                                        |root: &#name| Some(&root.#field_ident),
1689                                        |root: &mut #name| Some(&mut root.#field_ident),
1690                                    )
1691                                }
1692                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Mutex<#inner_ty>> {
1693                                    rust_key_paths::Kp::new(
1694                                        |root: &#name| root.#field_ident.as_ref(),
1695                                        |root: &mut #name| root.#field_ident.as_mut(),
1696                                    )
1697                                }
1698                            });
1699                        }
1700                        (WrapperKind::OptionMutex, Some(inner_ty)) => {
1701                            let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1702                            tokens.extend(quote! {
1703                                #[inline(always)]
1704                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1705                                    rust_key_paths::Kp::new(
1706                                        |root: &#name| Some(&root.#field_ident),
1707                                        |root: &mut #name| Some(&mut root.#field_ident),
1708                                    )
1709                                }
1710                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, parking_lot::Mutex<#inner_ty>> {
1711                                    rust_key_paths::Kp::new(
1712                                        |root: &#name| root.#field_ident.as_ref(),
1713                                        |root: &mut #name| root.#field_ident.as_mut(),
1714                                    )
1715                                }
1716                            });
1717                        }
1718                        (WrapperKind::OptionStdRwLock, Some(inner_ty)) => {
1719                            let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1720                            tokens.extend(quote! {
1721                                #[inline(always)]
1722                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1723                                    rust_key_paths::Kp::new(
1724                                        |root: &#name| Some(&root.#field_ident),
1725                                        |root: &mut #name| Some(&mut root.#field_ident),
1726                                    )
1727                                }
1728                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::RwLock<#inner_ty>> {
1729                                    rust_key_paths::Kp::new(
1730                                        |root: &#name| root.#field_ident.as_ref(),
1731                                        |root: &mut #name| root.#field_ident.as_mut(),
1732                                    )
1733                                }
1734                            });
1735                        }
1736                        (WrapperKind::OptionRwLock, Some(inner_ty)) => {
1737                            let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1738                            tokens.extend(quote! {
1739                                #[inline(always)]
1740                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1741                                    rust_key_paths::Kp::new(
1742                                        |root: &#name| Some(&root.#field_ident),
1743                                        |root: &mut #name| Some(&mut root.#field_ident),
1744                                    )
1745                                }
1746                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, parking_lot::RwLock<#inner_ty>> {
1747                                    rust_key_paths::Kp::new(
1748                                        |root: &#name| root.#field_ident.as_ref(),
1749                                        |root: &mut #name| root.#field_ident.as_mut(),
1750                                    )
1751                                }
1752                            });
1753                        }
1754                        (WrapperKind::Weak, Some(_inner_ty)) => {
1755                            // For Weak<T>, return keypath to container
1756                            tokens.extend(quote! {
1757                                #[inline(always)]
1758                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1759                                    rust_key_paths::Kp::new(
1760                                        |root: &#name| Some(&root.#field_ident),
1761                                        |_root: &mut #name| None, // Weak doesn't support mutable access
1762                                    )
1763                                }
1764                            });
1765                        }
1766                        (WrapperKind::Atomic, None | Some(_)) => {
1767                            // For atomic types: return keypath to the atomic (user calls .load()/.store())
1768                            tokens.extend(quote! {
1769                                #[inline(always)]
1770                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1771                                    rust_key_paths::Kp::new(
1772                                        |root: &#name| Some(&root.#field_ident),
1773                                        |root: &mut #name| Some(&mut root.#field_ident),
1774                                    )
1775                                }
1776                            });
1777                        }
1778                        (WrapperKind::OptionAtomic, Some(inner_ty)) => {
1779                            tokens.extend(quote! {
1780                                #[inline(always)]
1781                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1782                                    rust_key_paths::Kp::new(
1783                                        |root: &#name| root.#field_ident.as_ref(),
1784                                        |root: &mut #name| root.#field_ident.as_mut(),
1785                                    )
1786                                }
1787                            });
1788                        }
1789                        (WrapperKind::String, None) => {
1790                            tokens.extend(quote! {
1791                                #[inline(always)]
1792                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1793                                    rust_key_paths::Kp::new(
1794                                        |root: &#name| Some(&root.#field_ident),
1795                                        |root: &mut #name| Some(&mut root.#field_ident),
1796                                    )
1797                                }
1798                            });
1799                        }
1800                        (WrapperKind::OptionString, None) => {
1801                            tokens.extend(quote! {
1802                                #[inline(always)]
1803                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, std::string::String> {
1804                                    rust_key_paths::Kp::new(
1805                                        |root: &#name| root.#field_ident.as_ref(),
1806                                        |root: &mut #name| root.#field_ident.as_mut(),
1807                                    )
1808                                }
1809                            });
1810                        }
1811                        (WrapperKind::Cell, Some(_inner_ty)) => {
1812                            tokens.extend(quote! {
1813                                #[inline(always)]
1814                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1815                                    rust_key_paths::Kp::new(
1816                                        |root: &#name| Some(&root.#field_ident),
1817                                        |root: &mut #name| Some(&mut root.#field_ident),
1818                                    )
1819                                }
1820                            });
1821                        }
1822                        (WrapperKind::RefCell, Some(_inner_ty)) => {
1823                            tokens.extend(quote! {
1824                                #[inline(always)]
1825                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1826                                    rust_key_paths::Kp::new(
1827                                        |root: &#name| Some(&root.#field_ident),
1828                                        |root: &mut #name| Some(&mut root.#field_ident),
1829                                    )
1830                                }
1831                            });
1832                        }
1833                        (WrapperKind::OnceCell, Some(inner_ty)) => {
1834                            // OnceLock/OnceCell: keypath to inner value; get = .get() -> Option<&T>, set = None
1835                            tokens.extend(quote! {
1836                                #[inline(always)]
1837                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1838                                    rust_key_paths::Kp::new(
1839                                        |root: &#name| root.#field_ident.get(),
1840                                        |_root: &mut #name| None,
1841                                    )
1842                                }
1843                            });
1844                        }
1845                        (WrapperKind::Lazy, Some(inner_ty)) => {
1846                            // Lazy/LazyLock: keypath to inner value; get = .get() -> &T wrapped in Some, set = None
1847                            tokens.extend(quote! {
1848                                #[inline(always)]
1849                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1850                                    rust_key_paths::Kp::new(
1851                                        |root: &#name| Some(root.#field_ident.get()),
1852                                        |_root: &mut #name| None,
1853                                    )
1854                                }
1855                            });
1856                        }
1857                        (WrapperKind::PhantomData, Some(_inner_ty)) => {
1858                            tokens.extend(quote! {
1859                                #[inline(always)]
1860                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1861                                    rust_key_paths::Kp::new(
1862                                        |root: &#name| Some(&root.#field_ident),
1863                                        |root: &mut #name| Some(&mut root.#field_ident),
1864                                    )
1865                                }
1866                            });
1867                        }
1868                        (WrapperKind::Range, Some(_inner_ty)) => {
1869                            tokens.extend(quote! {
1870                                #[inline(always)]
1871                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1872                                    rust_key_paths::Kp::new(
1873                                        |root: &#name| Some(&root.#field_ident),
1874                                        |root: &mut #name| Some(&mut root.#field_ident),
1875                                    )
1876                                }
1877                            });
1878                        }
1879                        (WrapperKind::OptionCell, Some(_inner_ty)) => {
1880                            tokens.extend(quote! {
1881                                #[inline(always)]
1882                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1883                                    rust_key_paths::Kp::new(
1884                                        |root: &#name| Some(&root.#field_ident),
1885                                        |root: &mut #name| Some(&mut root.#field_ident),
1886                                    )
1887                                }
1888                            });
1889                        }
1890                        (WrapperKind::OptionRefCell, Some(inner_ty)) => {
1891                            // Option<RefCell<T>>: keypath to T via borrow()/borrow_mut(); get returns Option<Ref<V>> so caller holds guard (deref for &V)
1892                            tokens.extend(quote! {
1893                                #[inline(always)]
1894                                pub fn #kp_fn() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
1895                                    rust_key_paths::Kp::new(
1896                                        |root: &#name| root.#field_ident.as_ref().map(|r| r.borrow()),
1897                                        |root: &mut #name| root.#field_ident.as_ref().map(|r| r.borrow_mut()),
1898                                    )
1899                                }
1900                            });
1901                        }
1902                        (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
1903                            tokens.extend(quote! {
1904                                #[inline(always)]
1905                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1906                                    rust_key_paths::Kp::new(
1907                                        |root: &#name| root.#field_ident.as_ref().and_then(|c| c.get()),
1908                                        |_root: &mut #name| None,
1909                                    )
1910                                }
1911                            });
1912                        }
1913                        (WrapperKind::OptionLazy, Some(inner_ty)) => {
1914                            tokens.extend(quote! {
1915                                #[inline(always)]
1916                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1917                                    rust_key_paths::Kp::new(
1918                                        |root: &#name| root.#field_ident.as_ref().map(|c| c.get()),
1919                                        |_root: &mut #name| None,
1920                                    )
1921                                }
1922                            });
1923                        }
1924                        (WrapperKind::OptionPhantomData, Some(_inner_ty)) => {
1925                            tokens.extend(quote! {
1926                                #[inline(always)]
1927                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1928                                    rust_key_paths::Kp::new(
1929                                        |root: &#name| Some(&root.#field_ident),
1930                                        |root: &mut #name| Some(&mut root.#field_ident),
1931                                    )
1932                                }
1933                            });
1934                        }
1935                        (WrapperKind::OptionRange, Some(_inner_ty)) => {
1936                            tokens.extend(quote! {
1937                                #[inline(always)]
1938                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1939                                    rust_key_paths::Kp::new(
1940                                        |root: &#name| Some(&root.#field_ident),
1941                                        |root: &mut #name| Some(&mut root.#field_ident),
1942                                    )
1943                                }
1944                            });
1945                        }
1946                        (WrapperKind::Reference, Some(_inner_ty)) => {
1947                            // For reference types (&T, &str, &[T]): read-only, setter returns None
1948                            tokens.extend(quote! {
1949                                #[inline(always)]
1950                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1951                                    rust_key_paths::Kp::new(
1952                                        |root: &#name| Some(&root.#field_ident),
1953                                        |_root: &mut #name| None, // references: read-only
1954                                    )
1955                                }
1956                            });
1957                        }
1958                        (WrapperKind::None, None) => {
1959                            // For basic types, direct access
1960                            tokens.extend(quote! {
1961                                #[inline(always)]
1962                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1963                                    rust_key_paths::Kp::new(
1964                                        |root: &#name| Some(&root.#field_ident),
1965                                        |root: &mut #name| Some(&mut root.#field_ident),
1966                                    )
1967                                }
1968                            });
1969                        }
1970                        _ => {
1971                            // For unknown/complex nested types, return keypath to field itself
1972                            tokens.extend(quote! {
1973                                #[inline(always)]
1974                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1975                            rust_key_paths::Kp::new(
1976                                |root: &#name| Some(&root.#field_ident),
1977                                |root: &mut #name| Some(&mut root.#field_ident),
1978                            )
1979                        }
1980                            });
1981                        }
1982                    }
1983                }
1984                
1985                tokens
1986            }
1987            Fields::Unnamed(unnamed) => {
1988                let mut tokens = proc_macro2::TokenStream::new();
1989
1990                // Generate identity methods for the tuple struct
1991                tokens.extend(quote! {
1992                    /// Returns a generic identity keypath for this type
1993                    #[inline(always)]
1994                    pub fn identity_typed<Root, MutRoot>() -> rust_key_paths::Kp<
1995                        #name,
1996                        #name,
1997                        Root,
1998                        Root,
1999                        MutRoot,
2000                        MutRoot,
2001                        fn(Root) -> Option<Root>,
2002                        fn(MutRoot) -> Option<MutRoot>,
2003                    >
2004                    where
2005                        Root: std::borrow::Borrow<#name>,
2006                        MutRoot: std::borrow::BorrowMut<#name>,
2007                    {
2008                        rust_key_paths::Kp::new(
2009                            |r: Root| Some(r),
2010                            |r: MutRoot| Some(r)
2011                        )
2012                    }
2013
2014                    /// Returns a simple identity keypath for this type
2015                    #[inline(always)]
2016                    pub fn identity() -> rust_key_paths::KpType<'static, #name, #name> {
2017                        rust_key_paths::Kp::new(
2018                            |r: &#name| Some(r),
2019                            |r: &mut #name| Some(r)
2020                        )
2021                    }
2022                });
2023
2024                for (idx, field) in unnamed.unnamed.iter().enumerate() {
2025                    let idx_lit = syn::Index::from(idx);
2026                    let ty = &field.ty;
2027                    // Centralized keypath method names for tuple fields – change here to adjust for all types
2028                    let kp_fn = format_ident!("f{}", idx);
2029                    let kp_at_fn = format_ident!("f{}_at", idx);
2030
2031                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
2032
2033                    match (kind, inner_ty.clone()) {
2034                        (WrapperKind::Option, Some(inner_ty)) => {
2035                            tokens.extend(quote! {
2036                                #[inline(always)]
2037                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2038                                    rust_key_paths::Kp::new(
2039                                        |root: &#name| root.#idx_lit.as_ref(),
2040                                        |root: &mut #name| root.#idx_lit.as_mut(),
2041                                    )
2042                                }
2043                            });
2044                        }
2045                        (WrapperKind::OptionBox, Some(inner_ty)) => {
2046                            tokens.extend(quote! {
2047                                #[inline(always)]
2048                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2049                                    rust_key_paths::Kp::new(
2050                                        |root: &#name| root.#idx_lit.as_deref(),
2051                                        |root: &mut #name| root.#idx_lit.as_deref_mut(),
2052                                    )
2053                                }
2054                            });
2055                        }
2056                        (WrapperKind::OptionRc, Some(inner_ty)) => {
2057                            tokens.extend(quote! {
2058                                #[inline(always)]
2059                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2060                                    rust_key_paths::Kp::new(
2061                                        |root: &#name| root.#idx_lit.as_deref(),
2062                                        |root: &mut #name| root.#idx_lit.as_mut().and_then(std::rc::Rc::get_mut),
2063                                    )
2064                                }
2065                            });
2066                        }
2067                        (WrapperKind::OptionArc, Some(inner_ty)) => {
2068                            tokens.extend(quote! {
2069                                #[inline(always)]
2070                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2071                                    rust_key_paths::Kp::new(
2072                                        |root: &#name| root.#idx_lit.as_deref(),
2073                                        |root: &mut #name| root.#idx_lit.as_mut().and_then(std::sync::Arc::get_mut),
2074                                    )
2075                                }
2076                            });
2077                        }
2078                        (WrapperKind::OptionVecDeque, Some(_inner_ty))
2079                        | (WrapperKind::OptionLinkedList, Some(_inner_ty))
2080                        | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
2081                        | (WrapperKind::OptionHashSet, Some(_inner_ty))
2082                        | (WrapperKind::OptionBTreeSet, Some(_inner_ty))
2083                        | (WrapperKind::OptionResult, Some(_inner_ty))
2084                        | (WrapperKind::OptionBTreeMap, Some(_inner_ty)) => {
2085                            tokens.extend(quote! {
2086                                #[inline(always)]
2087                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2088                                    rust_key_paths::Kp::new(
2089                                        |root: &#name| Some(&root.#idx_lit),
2090                                        |root: &mut #name| Some(&mut root.#idx_lit),
2091                                    )
2092                                }
2093                            });
2094                        }
2095                        (WrapperKind::Vec, Some(inner_ty)) => {
2096                            tokens.extend(quote! {
2097                                #[inline(always)]
2098                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2099                                    rust_key_paths::Kp::new(
2100                                        |root: &#name| Some(&root.#idx_lit),
2101                                        |root: &mut #name| Some(&mut root.#idx_lit),
2102                                    )
2103                                }
2104                                #[inline(always)]
2105                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
2106                                    rust_key_paths::Kp::new(
2107                                        Box::new(move |root: &#name| root.#idx_lit.get(index)),
2108                                        Box::new(move |root: &mut #name| root.#idx_lit.get_mut(index)),
2109                                    )
2110                                }
2111                            });
2112                        }
2113                        (WrapperKind::HashMap, Some(inner_ty)) => {
2114                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
2115                                tokens.extend(quote! {
2116                                    #[inline(always)]
2117                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2118                                        rust_key_paths::Kp::new(
2119                                            |root: &#name| Some(&root.#idx_lit),
2120                                            |root: &mut #name| Some(&mut root.#idx_lit),
2121                                        )
2122                                    }
2123                                    #[inline(always)]
2124                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2125                                    where
2126                                        #key_ty: Clone + std::hash::Hash + Eq + 'static,
2127                                    {
2128                                        let key2 = key.clone();
2129                                        rust_key_paths::Kp::new(
2130                                            Box::new(move |root: &#name| root.#idx_lit.get(&key)),
2131                                            Box::new(move |root: &mut #name| root.#idx_lit.get_mut(&key2)),
2132                                        )
2133                                    }
2134                                });
2135                            } else {
2136                                tokens.extend(quote! {
2137                                    #[inline(always)]
2138                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2139                                        rust_key_paths::Kp::new(
2140                                            |root: &#name| Some(&root.#idx_lit),
2141                                            |root: &mut #name| Some(&mut root.#idx_lit),
2142                                        )
2143                                    }
2144                                });
2145                            }
2146                        }
2147                        (WrapperKind::BTreeMap, Some(inner_ty)) | (WrapperKind::BTreeMapOption, Some(inner_ty)) => {
2148                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
2149                                tokens.extend(quote! {
2150                                    #[inline(always)]
2151                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2152                                        rust_key_paths::Kp::new(
2153                                            |root: &#name| Some(&root.#idx_lit),
2154                                            |root: &mut #name| Some(&mut root.#idx_lit),
2155                                        )
2156                                    }
2157                                    #[inline(always)]
2158                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2159                                    where
2160                                        #key_ty: Clone + Ord + 'static,
2161                                    {
2162                                        let key2 = key.clone();
2163                                        rust_key_paths::Kp::new(
2164                                            Box::new(move |root: &#name| root.#idx_lit.get(&key)),
2165                                            Box::new(move |root: &mut #name| root.#idx_lit.get_mut(&key2)),
2166                                        )
2167                                    }
2168                                });
2169                            } else {
2170                                tokens.extend(quote! {
2171                                    #[inline(always)]
2172                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2173                                        rust_key_paths::Kp::new(
2174                                            |root: &#name| Some(&root.#idx_lit),
2175                                            |root: &mut #name| Some(&mut root.#idx_lit),
2176                                        )
2177                                    }
2178                                });
2179                            }
2180                        }
2181                        (WrapperKind::Box, Some(inner_ty)) => {
2182                            // Box: deref to inner (returns &T / &mut T)
2183                            tokens.extend(quote! {
2184                                #[inline(always)]
2185                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2186                                    rust_key_paths::Kp::new(
2187                                        |root: &#name| Some(&*root.#idx_lit),
2188                                        |root: &mut #name| Some(&mut *root.#idx_lit),
2189                                    )
2190                                }
2191                            });
2192                        }
2193                        (WrapperKind::BoxOption, Some(inner_ty)) => {
2194                            tokens.extend(quote! {
2195                                #[inline(always)]
2196                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2197                                    rust_key_paths::Kp::new(
2198                                        |root: &#name| (&*root.#idx_lit).as_ref(),
2199                                        |root: &mut #name| (&mut *root.#idx_lit).as_mut(),
2200                                    )
2201                                }
2202                            });
2203                        }
2204                        (WrapperKind::RcOption, Some(inner_ty)) => {
2205                            tokens.extend(quote! {
2206                                #[inline(always)]
2207                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2208                                    rust_key_paths::Kp::new(
2209                                        |root: &#name| (&*root.#idx_lit).as_ref(),
2210                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#idx_lit).and_then(std::option::Option::as_mut),
2211                                    )
2212                                }
2213                            });
2214                        }
2215                        (WrapperKind::ArcOption, Some(inner_ty)) => {
2216                            tokens.extend(quote! {
2217                                #[inline(always)]
2218                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2219                                    rust_key_paths::Kp::new(
2220                                        |root: &#name| (&*root.#idx_lit).as_ref(),
2221                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#idx_lit).and_then(std::option::Option::as_mut),
2222                                    )
2223                                }
2224                            });
2225                        }
2226                        (WrapperKind::Pin, Some(inner_ty)) => {
2227                            let kp_inner_fn = format_ident!("{}_inner", kp_fn);
2228                            tokens.extend(quote! {
2229                                #[inline(always)]
2230                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2231                                    rust_key_paths::Kp::new(
2232                                        |root: &#name| Some(&root.#idx_lit),
2233                                        |root: &mut #name| Some(&mut root.#idx_lit),
2234                                    )
2235                                }
2236                                #[inline(always)]
2237                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
2238                                where #inner_ty: std::marker::Unpin
2239                                {
2240                                    rust_key_paths::Kp::new(
2241                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#idx_lit).get_ref()),
2242                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#idx_lit).get_mut()),
2243                                    )
2244                                }
2245                            });
2246                        }
2247                        (WrapperKind::PinBox, Some(inner_ty)) => {
2248                            let kp_inner_fn = format_ident!("{}_inner", kp_fn);
2249                            tokens.extend(quote! {
2250                                #[inline(always)]
2251                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2252                                    rust_key_paths::Kp::new(
2253                                        |root: &#name| Some(&root.#idx_lit),
2254                                        |root: &mut #name| Some(&mut root.#idx_lit),
2255                                    )
2256                                }
2257                                #[inline(always)]
2258                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
2259                                where #inner_ty: std::marker::Unpin
2260                                {
2261                                    rust_key_paths::Kp::new(
2262                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#idx_lit).get_ref()),
2263                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#idx_lit).get_mut()),
2264                                    )
2265                                }
2266                            });
2267                        }
2268                        (WrapperKind::Rc, Some(inner_ty)) => {
2269                            tokens.extend(quote! {
2270                                #[inline(always)]
2271                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2272                                    rust_key_paths::Kp::new(
2273                                        |root: &#name| Some(root.#idx_lit.as_ref()),
2274                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#idx_lit),
2275                                    )
2276                                }
2277                            });
2278                        }
2279                        (WrapperKind::Arc, Some(inner_ty)) => {
2280                            tokens.extend(quote! {
2281                                #[inline(always)]
2282                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2283                                    rust_key_paths::Kp::new(
2284                                        |root: &#name| Some(root.#idx_lit.as_ref()),
2285                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#idx_lit),
2286                                    )
2287                                }
2288                            });
2289                        }
2290                        
2291                        (WrapperKind::Cow, Some(inner_ty)) => {
2292                            tokens.extend(quote! {
2293                                #[inline(always)]
2294                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2295                                    rust_key_paths::Kp::new(
2296                                        |root: &#name| Some(root.#idx_lit.as_ref()),
2297                                        |root: &mut #name| Some(root.#idx_lit.to_mut()),
2298                                    )
2299                                }
2300                            });
2301                        }
2302                        
2303                        (WrapperKind::OptionCow, Some(inner_ty)) => {
2304                            tokens.extend(quote! {
2305                                #[inline(always)]
2306                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2307                                    rust_key_paths::Kp::new(
2308                                        |root: &#name| root.#idx_lit.as_ref().map(|c| c.as_ref()),
2309                                        |root: &mut #name| root.#idx_lit.as_mut().map(|c| c.to_mut()),
2310                                    )
2311                                }
2312                            });
2313                        }
2314                        (WrapperKind::OptionTagged, Some(inner_ty)) => {
2315                            tokens.extend(quote! {
2316                                #[inline(always)]
2317                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2318                                    rust_key_paths::Kp::new(
2319                                        |root: &#name| root.#idx_lit.as_ref().map(|t| std::ops::Deref::deref(t)),
2320                                        |root: &mut #name| root.#idx_lit.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
2321                                    )
2322                                }
2323                            });
2324                        }
2325                        (WrapperKind::OptionReference, Some(inner_ty)) => {
2326                            tokens.extend(quote! {
2327                                #[inline(always)]
2328                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2329                                    rust_key_paths::Kp::new(
2330                                        |root: &#name| root.#idx_lit.as_ref(),
2331                                        |_root: &mut #name| None,
2332                                    )
2333                                }
2334                            });
2335                        }
2336                        (WrapperKind::HashSet, Some(inner_ty)) | (WrapperKind::HashSetOption, Some(inner_ty)) => {
2337                            let kp_at_fn = format_ident!("f{}_at", idx);
2338
2339                            tokens.extend(quote! {
2340                                #[inline(always)]
2341                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2342                                    rust_key_paths::Kp::new(
2343                                        |root: &#name| Some(&root.#idx_lit),
2344                                        |root: &mut #name| Some(&mut root.#idx_lit),
2345                                    )
2346                                }
2347
2348                                /// _at: check if element exists and get reference.
2349                                /// HashSet does not allow mutable element access (would break hash invariant).
2350                                #[inline(always)]
2351                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2352                                where
2353                                    #inner_ty: Clone + std::hash::Hash + Eq + 'static,
2354                                {
2355                                    rust_key_paths::Kp::new(
2356                                        Box::new(move |root: &#name| root.#idx_lit.get(&key)),
2357                                        Box::new(move |_root: &mut #name| None),
2358                                    )
2359                                }
2360                            });
2361                        }
2362                        (WrapperKind::BTreeSet, Some(inner_ty)) | (WrapperKind::BTreeSetOption, Some(inner_ty)) => {
2363                            let kp_at_fn = format_ident!("f{}_at", idx);
2364
2365                            tokens.extend(quote! {
2366                                #[inline(always)]
2367                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2368                                    rust_key_paths::Kp::new(
2369                                        |root: &#name| Some(&root.#idx_lit),
2370                                        |root: &mut #name| Some(&mut root.#idx_lit),
2371                                    )
2372                                }
2373
2374                                /// _at: check if element exists and get reference.
2375                                /// BTreeSet does not allow mutable element access (would break ordering invariant).
2376                                #[inline(always)]
2377                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2378                                where
2379                                    #inner_ty: Clone + Ord + 'static,
2380                                {
2381                                    rust_key_paths::Kp::new(
2382                                        Box::new(move |root: &#name| root.#idx_lit.get(&key)),
2383                                        Box::new(move |_root: &mut #name| None),
2384                                    )
2385                                }
2386                            });
2387                        }
2388                        (WrapperKind::VecDeque, Some(inner_ty)) | (WrapperKind::VecDequeOption, Some(inner_ty)) => {
2389                            tokens.extend(quote! {
2390                                #[inline(always)]
2391                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2392                                    rust_key_paths::Kp::new(
2393                                        |root: &#name| Some(&root.#idx_lit),
2394                                        |root: &mut #name| Some(&mut root.#idx_lit),
2395                                    )
2396                                }
2397                                #[inline(always)]
2398                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
2399                                    rust_key_paths::Kp::new(
2400                                        Box::new(move |root: &#name| root.#idx_lit.get(index)),
2401                                        Box::new(move |root: &mut #name| root.#idx_lit.get_mut(index)),
2402                                    )
2403                                }
2404                            });
2405                        }
2406                        (WrapperKind::LinkedList, Some(_inner_ty)) | (WrapperKind::LinkedListOption, Some(_inner_ty)) => {
2407                            tokens.extend(quote! {
2408                                #[inline(always)]
2409                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2410                                    rust_key_paths::Kp::new(
2411                                        |root: &#name| Some(&root.#idx_lit),
2412                                        |root: &mut #name| Some(&mut root.#idx_lit),
2413                                    )
2414                                }
2415                            });
2416                        }
2417                        (WrapperKind::BinaryHeap, Some(_inner_ty)) | (WrapperKind::BinaryHeapOption, Some(_inner_ty)) => {
2418                            tokens.extend(quote! {
2419                                #[inline(always)]
2420                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2421                                    rust_key_paths::Kp::new(
2422                                        |root: &#name| Some(&root.#idx_lit),
2423                                        |root: &mut #name| Some(&mut root.#idx_lit),
2424                                    )
2425                                }
2426                            });
2427                        }
2428                        (WrapperKind::Result, Some(inner_ty)) => {
2429                            tokens.extend(quote! {
2430                                #[inline(always)]
2431                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2432                                    rust_key_paths::Kp::new(
2433                                        |root: &#name| root.#idx_lit.as_ref().ok(),
2434                                        |root: &mut #name| root.#idx_lit.as_mut().ok(),
2435                                    )
2436                                }
2437                            });
2438                        }
2439                        (WrapperKind::Mutex, Some(_inner_ty))
2440                        | (WrapperKind::StdMutex, Some(_inner_ty)) => {
2441                            tokens.extend(quote! {
2442                                #[inline(always)]
2443                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2444                                    rust_key_paths::Kp::new(
2445                                        |root: &#name| Some(&root.#idx_lit),
2446                                        |root: &mut #name| Some(&mut root.#idx_lit),
2447                                    )
2448                                }
2449                            });
2450                        }
2451                        (WrapperKind::RwLock, Some(_inner_ty))
2452                        | (WrapperKind::StdRwLock, Some(_inner_ty)) => {
2453                            tokens.extend(quote! {
2454                                #[inline(always)]
2455                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2456                                    rust_key_paths::Kp::new(
2457                                        |root: &#name| Some(&root.#idx_lit),
2458                                        |root: &mut #name| Some(&mut root.#idx_lit),
2459                                    )
2460                                }
2461                            });
2462                        }
2463                        (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
2464                            let kp_async_fn = format_ident!("f{}_kp", idx);
2465                            tokens.extend(quote! {
2466                                #[inline(always)]
2467                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2468                                    rust_key_paths::Kp::new(
2469                                        |root: &#name| Some(&root.#idx_lit),
2470                                        |root: &mut #name| Some(&mut root.#idx_lit),
2471                                    )
2472                                }
2473                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #ty, #inner_ty> {
2474                                    rust_key_paths::async_lock::AsyncLockKp::new(
2475                                        rust_key_paths::Kp::new(
2476                                            |root: &#name| Some(&root.#idx_lit),
2477                                            |root: &mut #name| Some(&mut root.#idx_lit),
2478                                        ),
2479                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
2480                                        rust_key_paths::Kp::new(
2481                                            |v: &#inner_ty| Some(v),
2482                                            |v: &mut #inner_ty| Some(v),
2483                                        ),
2484                                    )
2485                                }
2486                            });
2487                        }
2488                        (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
2489                            let kp_async_fn = format_ident!("f{}_kp", idx);
2490                            tokens.extend(quote! {
2491                                #[inline(always)]
2492                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2493                                    rust_key_paths::Kp::new(
2494                                        |root: &#name| Some(&root.#idx_lit),
2495                                        |root: &mut #name| Some(&mut root.#idx_lit),
2496                                    )
2497                                }
2498                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #ty, #inner_ty> {
2499                                    rust_key_paths::async_lock::AsyncLockKp::new(
2500                                        rust_key_paths::Kp::new(
2501                                            |root: &#name| Some(&root.#idx_lit),
2502                                            |root: &mut #name| Some(&mut root.#idx_lit),
2503                                        ),
2504                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
2505                                        rust_key_paths::Kp::new(
2506                                            |v: &#inner_ty| Some(v),
2507                                            |v: &mut #inner_ty| Some(v),
2508                                        ),
2509                                    )
2510                                }
2511                            });
2512                        }
2513                        (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
2514                            let kp_async_fn = format_ident!("f{}_kp", idx);
2515                            tokens.extend(quote! {
2516                                #[inline(always)]
2517                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2518                                    rust_key_paths::Kp::new(
2519                                        |root: &#name| Some(&root.#idx_lit),
2520                                        |root: &mut #name| Some(&mut root.#idx_lit),
2521                                    )
2522                                }
2523                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
2524                                    rust_key_paths::async_lock::AsyncLockKp::new(
2525                                        rust_key_paths::Kp::new(
2526                                            |root: &#name| root.#idx_lit.as_ref(),
2527                                            |root: &mut #name| root.#idx_lit.as_mut(),
2528                                        ),
2529                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
2530                                        rust_key_paths::Kp::new(
2531                                            |v: &#inner_ty| Some(v),
2532                                            |v: &mut #inner_ty| Some(v),
2533                                        ),
2534                                    )
2535                                }
2536                            });
2537                        }
2538                        (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
2539                            let kp_async_fn = format_ident!("f{}_kp", idx);
2540                            tokens.extend(quote! {
2541                                #[inline(always)]
2542                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2543                                    rust_key_paths::Kp::new(
2544                                        |root: &#name| Some(&root.#idx_lit),
2545                                        |root: &mut #name| Some(&mut root.#idx_lit),
2546                                    )
2547                                }
2548                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
2549                                    rust_key_paths::async_lock::AsyncLockKp::new(
2550                                        rust_key_paths::Kp::new(
2551                                            |root: &#name| root.#idx_lit.as_ref(),
2552                                            |root: &mut #name| root.#idx_lit.as_mut(),
2553                                        ),
2554                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
2555                                        rust_key_paths::Kp::new(
2556                                            |v: &#inner_ty| Some(v),
2557                                            |v: &mut #inner_ty| Some(v),
2558                                        ),
2559                                    )
2560                                }
2561                            });
2562                        }
2563                        (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
2564                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2565                            tokens.extend(quote! {
2566                                #[inline(always)]
2567                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2568                                    rust_key_paths::Kp::new(
2569                                        |root: &#name| Some(&root.#idx_lit),
2570                                        |root: &mut #name| Some(&mut root.#idx_lit),
2571                                    )
2572                                }
2573                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::Mutex<#inner_ty>>> {
2574                                    rust_key_paths::Kp::new(
2575                                        |root: &#name| root.#idx_lit.as_ref(),
2576                                        |root: &mut #name| root.#idx_lit.as_mut(),
2577                                    )
2578                                }
2579                            });
2580                        }
2581                        (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
2582                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2583                            tokens.extend(quote! {
2584                                #[inline(always)]
2585                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2586                                    rust_key_paths::Kp::new(
2587                                        |root: &#name| Some(&root.#idx_lit),
2588                                        |root: &mut #name| Some(&mut root.#idx_lit),
2589                                    )
2590                                }
2591                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>> {
2592                                    rust_key_paths::Kp::new(
2593                                        |root: &#name| root.#idx_lit.as_ref(),
2594                                        |root: &mut #name| root.#idx_lit.as_mut(),
2595                                    )
2596                                }
2597                            });
2598                        }
2599                        (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
2600                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2601                            tokens.extend(quote! {
2602                                #[inline(always)]
2603                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2604                                    rust_key_paths::Kp::new(
2605                                        |root: &#name| Some(&root.#idx_lit),
2606                                        |root: &mut #name| Some(&mut root.#idx_lit),
2607                                    )
2608                                }
2609                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::RwLock<#inner_ty>>> {
2610                                    rust_key_paths::Kp::new(
2611                                        |root: &#name| root.#idx_lit.as_ref(),
2612                                        |root: &mut #name| root.#idx_lit.as_mut(),
2613                                    )
2614                                }
2615                            });
2616                        }
2617                        (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
2618                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2619                            tokens.extend(quote! {
2620                                #[inline(always)]
2621                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2622                                    rust_key_paths::Kp::new(
2623                                        |root: &#name| Some(&root.#idx_lit),
2624                                        |root: &mut #name| Some(&mut root.#idx_lit),
2625                                    )
2626                                }
2627                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>> {
2628                                    rust_key_paths::Kp::new(
2629                                        |root: &#name| root.#idx_lit.as_ref(),
2630                                        |root: &mut #name| root.#idx_lit.as_mut(),
2631                                    )
2632                                }
2633                            });
2634                        }
2635                        (WrapperKind::OptionStdMutex, Some(inner_ty)) => {
2636                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2637                            tokens.extend(quote! {
2638                                #[inline(always)]
2639                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2640                                    rust_key_paths::Kp::new(
2641                                        |root: &#name| Some(&root.#idx_lit),
2642                                        |root: &mut #name| Some(&mut root.#idx_lit),
2643                                    )
2644                                }
2645                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Mutex<#inner_ty>> {
2646                                    rust_key_paths::Kp::new(
2647                                        |root: &#name| root.#idx_lit.as_ref(),
2648                                        |root: &mut #name| root.#idx_lit.as_mut(),
2649                                    )
2650                                }
2651                            });
2652                        }
2653                        (WrapperKind::OptionMutex, Some(inner_ty)) => {
2654                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2655                            tokens.extend(quote! {
2656                                #[inline(always)]
2657                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2658                                    rust_key_paths::Kp::new(
2659                                        |root: &#name| Some(&root.#idx_lit),
2660                                        |root: &mut #name| Some(&mut root.#idx_lit),
2661                                    )
2662                                }
2663                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, parking_lot::Mutex<#inner_ty>> {
2664                                    rust_key_paths::Kp::new(
2665                                        |root: &#name| root.#idx_lit.as_ref(),
2666                                        |root: &mut #name| root.#idx_lit.as_mut(),
2667                                    )
2668                                }
2669                            });
2670                        }
2671                        (WrapperKind::OptionStdRwLock, Some(inner_ty)) => {
2672                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2673                            tokens.extend(quote! {
2674                                #[inline(always)]
2675                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2676                                    rust_key_paths::Kp::new(
2677                                        |root: &#name| Some(&root.#idx_lit),
2678                                        |root: &mut #name| Some(&mut root.#idx_lit),
2679                                    )
2680                                }
2681                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::RwLock<#inner_ty>> {
2682                                    rust_key_paths::Kp::new(
2683                                        |root: &#name| root.#idx_lit.as_ref(),
2684                                        |root: &mut #name| root.#idx_lit.as_mut(),
2685                                    )
2686                                }
2687                            });
2688                        }
2689                        (WrapperKind::OptionRwLock, Some(inner_ty)) => {
2690                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2691                            tokens.extend(quote! {
2692                                #[inline(always)]
2693                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2694                                    rust_key_paths::Kp::new(
2695                                        |root: &#name| Some(&root.#idx_lit),
2696                                        |root: &mut #name| Some(&mut root.#idx_lit),
2697                                    )
2698                                }
2699                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, parking_lot::RwLock<#inner_ty>> {
2700                                    rust_key_paths::Kp::new(
2701                                        |root: &#name| root.#idx_lit.as_ref(),
2702                                        |root: &mut #name| root.#idx_lit.as_mut(),
2703                                    )
2704                                }
2705                            });
2706                        }
2707                        (WrapperKind::Weak, Some(_inner_ty)) => {
2708                            tokens.extend(quote! {
2709                                #[inline(always)]
2710                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2711                                    rust_key_paths::Kp::new(
2712                                        |root: &#name| Some(&root.#idx_lit),
2713                                        |_root: &mut #name| None,
2714                                    )
2715                                }
2716                            });
2717                        }
2718                        (WrapperKind::Atomic, None | Some(_)) => {
2719                            tokens.extend(quote! {
2720                                #[inline(always)]
2721                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2722                                    rust_key_paths::Kp::new(
2723                                        |root: &#name| Some(&root.#idx_lit),
2724                                        |root: &mut #name| Some(&mut root.#idx_lit),
2725                                    )
2726                                }
2727                            });
2728                        }
2729                        (WrapperKind::OptionAtomic, Some(inner_ty)) => {
2730                            tokens.extend(quote! {
2731                                #[inline(always)]
2732                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2733                                    rust_key_paths::Kp::new(
2734                                        |root: &#name| root.#idx_lit.as_ref(),
2735                                        |root: &mut #name| root.#idx_lit.as_mut(),
2736                                    )
2737                                }
2738                            });
2739                        }
2740                        (WrapperKind::String, None) => {
2741                            tokens.extend(quote! {
2742                                #[inline(always)]
2743                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2744                                    rust_key_paths::Kp::new(
2745                                        |root: &#name| Some(&root.#idx_lit),
2746                                        |root: &mut #name| Some(&mut root.#idx_lit),
2747                                    )
2748                                }
2749                            });
2750                        }
2751                        (WrapperKind::OptionString, None) => {
2752                            tokens.extend(quote! {
2753                                #[inline(always)]
2754                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, std::string::String> {
2755                                    rust_key_paths::Kp::new(
2756                                        |root: &#name| root.#idx_lit.as_ref(),
2757                                        |root: &mut #name| root.#idx_lit.as_mut(),
2758                                    )
2759                                }
2760                            });
2761                        }
2762                        (WrapperKind::OnceCell, Some(inner_ty)) => {
2763                            tokens.extend(quote! {
2764                                #[inline(always)]
2765                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2766                                    rust_key_paths::Kp::new(
2767                                        |root: &#name| root.#idx_lit.get(),
2768                                        |_root: &mut #name| None,
2769                                    )
2770                                }
2771                            });
2772                        }
2773                        (WrapperKind::Lazy, Some(inner_ty)) => {
2774                            tokens.extend(quote! {
2775                                #[inline(always)]
2776                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2777                                    rust_key_paths::Kp::new(
2778                                        |root: &#name| Some(root.#idx_lit.get()),
2779                                        |_root: &mut #name| None,
2780                                    )
2781                                }
2782                            });
2783                        }
2784                        (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
2785                            tokens.extend(quote! {
2786                                #[inline(always)]
2787                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2788                                    rust_key_paths::Kp::new(
2789                                        |root: &#name| root.#idx_lit.as_ref().and_then(|c| c.get()),
2790                                        |_root: &mut #name| None,
2791                                    )
2792                                }
2793                            });
2794                        }
2795                        (WrapperKind::OptionLazy, Some(inner_ty)) => {
2796                            tokens.extend(quote! {
2797                                #[inline(always)]
2798                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2799                                    rust_key_paths::Kp::new(
2800                                        |root: &#name| root.#idx_lit.as_ref().map(|c| c.get()),
2801                                        |_root: &mut #name| None,
2802                                    )
2803                                }
2804                            });
2805                        }
2806                        (WrapperKind::Cell, Some(_inner_ty)) | (WrapperKind::RefCell, Some(_inner_ty))
2807                        | (WrapperKind::PhantomData, Some(_inner_ty)) | (WrapperKind::Range, Some(_inner_ty))
2808                        | (WrapperKind::OptionCell, Some(_inner_ty))
2809                        | (WrapperKind::OptionPhantomData, Some(_inner_ty)) | (WrapperKind::OptionRange, Some(_inner_ty)) => {
2810                            tokens.extend(quote! {
2811                                #[inline(always)]
2812                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2813                                    rust_key_paths::Kp::new(
2814                                        |root: &#name| Some(&root.#idx_lit),
2815                                        |root: &mut #name| Some(&mut root.#idx_lit),
2816                                    )
2817                                }
2818                            });
2819                        }
2820                        (WrapperKind::OptionRefCell, Some(inner_ty)) => {
2821                            tokens.extend(quote! {
2822                                #[inline(always)]
2823                                pub fn #kp_fn() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
2824                                    rust_key_paths::Kp::new(
2825                                        |root: &#name| root.#idx_lit.as_ref().map(|r| r.borrow()),
2826                                        |root: &mut #name| root.#idx_lit.as_ref().map(|r| r.borrow_mut()),
2827                                    )
2828                                }
2829                            });
2830                        }
2831                        (WrapperKind::Reference, Some(_inner_ty)) => {
2832                            tokens.extend(quote! {
2833                                #[inline(always)]
2834                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2835                                    rust_key_paths::Kp::new(
2836                                        |root: &#name| Some(&root.#idx_lit),
2837                                        |_root: &mut #name| None,
2838                                    )
2839                                }
2840                            });
2841                        }
2842                        (WrapperKind::None, None) => {
2843                            tokens.extend(quote! {
2844                                #[inline(always)]
2845                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2846                                    rust_key_paths::Kp::new(
2847                                        |root: &#name| Some(&root.#idx_lit),
2848                                        |root: &mut #name| Some(&mut root.#idx_lit),
2849                                    )
2850                                }
2851                            });
2852                        }
2853                        _ => {
2854                            tokens.extend(quote! {
2855                                #[inline(always)]
2856                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2857                                    rust_key_paths::Kp::new(
2858                                        |root: &#name| Some(&root.#idx_lit),
2859                                        |root: &mut #name| Some(&mut root.#idx_lit),
2860                                    )
2861                                }
2862                            });
2863                        }
2864                    }
2865                }
2866
2867                tokens
2868            }
2869            Fields::Unit => {
2870                return syn::Error::new(input_span, "Kp derive does not support unit structs")
2871                .to_compile_error()
2872                .into();
2873            }
2874        },
2875        Data::Enum(data_enum) => {
2876            let mut tokens = proc_macro2::TokenStream::new();
2877
2878            // Generate identity methods for the enum
2879            tokens.extend(quote! {
2880                /// Returns a generic identity keypath for this type
2881                #[inline(always)]
2882                pub fn identity_typed<Root, MutRoot>() -> rust_key_paths::Kp<
2883                    #name,
2884                    #name,
2885                    Root,
2886                    Root,
2887                    MutRoot,
2888                    MutRoot,
2889                    fn(Root) -> Option<Root>,
2890                    fn(MutRoot) -> Option<MutRoot>,
2891                >
2892                where
2893                    Root: std::borrow::Borrow<#name>,
2894                    MutRoot: std::borrow::BorrowMut<#name>,
2895                {
2896                    rust_key_paths::Kp::new(
2897                        |r: Root| Some(r),
2898                        |r: MutRoot| Some(r)
2899                    )
2900                }
2901
2902                /// Returns a simple identity keypath for this type
2903                #[inline(always)]
2904                pub fn identity() -> rust_key_paths::KpType<'static, #name, #name> {
2905                    rust_key_paths::Kp::new(
2906                        |r: &#name| Some(r),
2907                        |r: &mut #name| Some(r)
2908                    )
2909                }
2910            });
2911
2912            for variant in data_enum.variants.iter() {
2913                let v_ident = &variant.ident;
2914                let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
2915
2916                match &variant.fields {
2917                    Fields::Unit => {
2918                        // Unit variant - return keypath that checks if enum matches variant
2919                        tokens.extend(quote! {
2920                            #[inline(always)]
2921                            pub fn #snake() -> rust_key_paths::KpType<'static, #name, ()> {
2922                                rust_key_paths::Kp::new(
2923                                    |root: &#name| match root {
2924                                        #name::#v_ident => {
2925                                            static UNIT: () = ();
2926                                            Some(&UNIT)
2927                                        },
2928                                        _ => None,
2929                                    },
2930                                    |_root: &mut #name| None, // Can't mutate unit variant
2931                                )
2932                            }
2933                        });
2934                    }
2935                    Fields::Unnamed(unnamed) => {
2936                        if unnamed.unnamed.len() == 1 {
2937                            // Single-field tuple variant
2938                            let field_ty = &unnamed.unnamed[0].ty;
2939                            let (kind, inner_ty) = extract_wrapper_inner_type(field_ty);
2940
2941                            match (kind, inner_ty.clone()) {
2942                                (WrapperKind::Option, Some(inner_ty)) => {
2943                                    tokens.extend(quote! {
2944                                        #[inline(always)]
2945                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2946                                            rust_key_paths::Kp::new(
2947                                                |root: &#name| match root {
2948                                                    #name::#v_ident(inner) => inner.as_ref(),
2949                                                    _ => None,
2950                                                },
2951                                                |root: &mut #name| match root {
2952                                                    #name::#v_ident(inner) => inner.as_mut(),
2953                                                    _ => None,
2954                                                },
2955                                            )
2956                                        }
2957                                    });
2958                                }
2959                                (WrapperKind::OptionVecDeque, Some(_inner_ty))
2960                                | (WrapperKind::OptionLinkedList, Some(_inner_ty))
2961                                | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
2962                                | (WrapperKind::OptionHashSet, Some(_inner_ty))
2963                                | (WrapperKind::OptionBTreeSet, Some(_inner_ty))
2964                                | (WrapperKind::OptionResult, Some(_inner_ty))
2965                                | (WrapperKind::OptionBTreeMap, Some(_inner_ty)) => {
2966                                    tokens.extend(quote! {
2967                                        #[inline(always)]
2968                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2969                                            rust_key_paths::Kp::new(
2970                                                |root: &#name| match root {
2971                                                    #name::#v_ident(inner) => Some(inner),
2972                                                    _ => None,
2973                                                },
2974                                                |root: &mut #name| match root {
2975                                                    #name::#v_ident(inner) => Some(inner),
2976                                                    _ => None,
2977                                                },
2978                                            )
2979                                        }
2980                                    });
2981                                }
2982                                (WrapperKind::Vec, Some(inner_ty)) => {
2983                                    tokens.extend(quote! {
2984                                        #[inline(always)]
2985                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2986                                            rust_key_paths::Kp::new(
2987                                                |root: &#name| match root {
2988                                                    #name::#v_ident(inner) => inner.first(),
2989                                                    _ => None,
2990                                                },
2991                                                |root: &mut #name| match root {
2992                                                    #name::#v_ident(inner) => inner.first_mut(),
2993                                                    _ => None,
2994                                                },
2995                                            )
2996                                        }
2997                                    });
2998                                }
2999                                (WrapperKind::Box, Some(inner_ty)) => {
3000                                    // Box in enum: deref to inner (&T / &mut T)
3001                                    tokens.extend(quote! {
3002                                        #[inline(always)]
3003                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3004                                            rust_key_paths::Kp::new(
3005                                                |root: &#name| match root {
3006                                                    #name::#v_ident(inner) => Some(&**inner),
3007                                                    _ => None,
3008                                                },
3009                                                |root: &mut #name| match root {
3010                                                    #name::#v_ident(inner) => Some(&mut **inner),
3011                                                    _ => None,
3012                                                },
3013                                            )
3014                                        }
3015                                    });
3016                                }
3017                                (WrapperKind::Pin, Some(inner_ty)) => {
3018                                    let snake_inner = format_ident!("{}_inner", snake);
3019                                    tokens.extend(quote! {
3020                                        #[inline(always)]
3021                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3022                                            rust_key_paths::Kp::new(
3023                                                |root: &#name| match root {
3024                                                    #name::#v_ident(inner) => Some(inner),
3025                                                    _ => None,
3026                                                },
3027                                                |root: &mut #name| match root {
3028                                                    #name::#v_ident(inner) => Some(inner),
3029                                                    _ => None,
3030                                                },
3031                                            )
3032                                        }
3033                                        #[inline(always)]
3034                                        pub fn #snake_inner() -> rust_key_paths::KpType<'static, #name, #inner_ty>
3035                                        where #inner_ty: std::marker::Unpin
3036                                        {
3037                                            rust_key_paths::Kp::new(
3038                                                |root: &#name| match root {
3039                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_ref(inner).get_ref()),
3040                                                    _ => None,
3041                                                },
3042                                                |root: &mut #name| match root {
3043                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_mut(inner).get_mut()),
3044                                                    _ => None,
3045                                                },
3046                                            )
3047                                        }
3048                                    });
3049                                }
3050                                (WrapperKind::PinBox, Some(inner_ty)) => {
3051                                    let snake_inner = format_ident!("{}_inner", snake);
3052                                    tokens.extend(quote! {
3053                                        #[inline(always)]
3054                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3055                                            rust_key_paths::Kp::new(
3056                                                |root: &#name| match root {
3057                                                    #name::#v_ident(inner) => Some(inner),
3058                                                    _ => None,
3059                                                },
3060                                                |root: &mut #name| match root {
3061                                                    #name::#v_ident(inner) => Some(inner),
3062                                                    _ => None,
3063                                                },
3064                                            )
3065                                        }
3066                                        #[inline(always)]
3067                                        pub fn #snake_inner() -> rust_key_paths::KpType<'static, #name, #inner_ty>
3068                                        where #inner_ty: std::marker::Unpin
3069                                        {
3070                                            rust_key_paths::Kp::new(
3071                                                |root: &#name| match root {
3072                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_ref(inner).get_ref()),
3073                                                    _ => None,
3074                                                },
3075                                                |root: &mut #name| match root {
3076                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_mut(inner).get_mut()),
3077                                                    _ => None,
3078                                                },
3079                                            )
3080                                        }
3081                                    });
3082                                }
3083                                (WrapperKind::Rc, Some(inner_ty)) => {
3084                                    tokens.extend(quote! {
3085                                        #[inline(always)]
3086                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3087                                            rust_key_paths::Kp::new(
3088                                                |root: &#name| match root {
3089                                                    #name::#v_ident(inner) => Some(inner.as_ref()),
3090                                                    _ => None,
3091                                                },
3092                                                |root: &mut #name| match root {
3093                                                    #name::#v_ident(inner) => std::rc::Rc::get_mut(inner),
3094                                                    _ => None,
3095                                                },
3096                                            )
3097                                        }
3098                                    });
3099                                }
3100                                (WrapperKind::Arc, Some(inner_ty)) => {
3101                                    tokens.extend(quote! {
3102                                        #[inline(always)]
3103                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3104                                            rust_key_paths::Kp::new(
3105                                                |root: &#name| match root {
3106                                                    #name::#v_ident(inner) => Some(inner.as_ref()),
3107                                                    _ => None,
3108                                                },
3109                                                |root: &mut #name| match root {
3110                                                    #name::#v_ident(inner) => std::sync::Arc::get_mut(inner),
3111                                                    _ => None,
3112                                                },
3113                                            )
3114                                        }
3115                                    });
3116                                }
3117                                (WrapperKind::StdArcRwLock, Some(inner_ty)) => {
3118                                    let snake_lock = format_ident!("{}_lock", snake);
3119                                    tokens.extend(quote! {
3120                                        #[inline(always)]
3121                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3122                                            rust_key_paths::Kp::new(
3123                                                |root: &#name| match root {
3124                                                    #name::#v_ident(inner) => Some(inner),
3125                                                    _ => None,
3126                                                },
3127                                                |root: &mut #name| match root {
3128                                                    #name::#v_ident(inner) => Some(inner),
3129                                                    _ => None,
3130                                                },
3131                                            )
3132                                        }
3133                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, #field_ty, #inner_ty> {
3134                                            rust_key_paths::lock::LockKp::new(
3135                                                rust_key_paths::Kp::new(
3136                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3137                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3138                                                ),
3139                                                rust_key_paths::lock::ArcRwLockAccess::new(),
3140                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3141                                            )
3142                                        }
3143                                    });
3144                                }
3145                                (WrapperKind::StdArcMutex, Some(inner_ty)) => {
3146                                    let snake_lock = format_ident!("{}_lock", snake);
3147                                    tokens.extend(quote! {
3148                                        #[inline(always)]
3149                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3150                                            rust_key_paths::Kp::new(
3151                                                |root: &#name| match root {
3152                                                    #name::#v_ident(inner) => Some(inner),
3153                                                    _ => None,
3154                                                },
3155                                                |root: &mut #name| match root {
3156                                                    #name::#v_ident(inner) => Some(inner),
3157                                                    _ => None,
3158                                                },
3159                                            )
3160                                        }
3161                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcMutexFor<#name, #field_ty, #inner_ty> {
3162                                            rust_key_paths::lock::LockKp::new(
3163                                                rust_key_paths::Kp::new(
3164                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3165                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3166                                                ),
3167                                                rust_key_paths::lock::ArcMutexAccess::new(),
3168                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3169                                            )
3170                                        }
3171                                    });
3172                                }
3173                                (WrapperKind::ArcRwLock, Some(inner_ty)) => {
3174                                    let snake_lock = format_ident!("{}_lock", snake);
3175                                    tokens.extend(quote! {
3176                                        #[inline(always)]
3177                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3178                                            rust_key_paths::Kp::new(
3179                                                |root: &#name| match root {
3180                                                    #name::#v_ident(inner) => Some(inner),
3181                                                    _ => None,
3182                                                },
3183                                                |root: &mut #name| match root {
3184                                                    #name::#v_ident(inner) => Some(inner),
3185                                                    _ => None,
3186                                                },
3187                                            )
3188                                        }
3189                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, #field_ty, #inner_ty> {
3190                                            rust_key_paths::lock::LockKp::new(
3191                                                rust_key_paths::Kp::new(
3192                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3193                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3194                                                ),
3195                                                rust_key_paths::lock::ParkingLotRwLockAccess::new(),
3196                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3197                                            )
3198                                        }
3199                                    });
3200                                }
3201                                (WrapperKind::ArcMutex, Some(inner_ty)) => {
3202                                    let snake_lock = format_ident!("{}_lock", snake);
3203                                    tokens.extend(quote! {
3204                                        #[inline(always)]
3205                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3206                                            rust_key_paths::Kp::new(
3207                                                |root: &#name| match root {
3208                                                    #name::#v_ident(inner) => Some(inner),
3209                                                    _ => None,
3210                                                },
3211                                                |root: &mut #name| match root {
3212                                                    #name::#v_ident(inner) => Some(inner),
3213                                                    _ => None,
3214                                                },
3215                                            )
3216                                        }
3217                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, #field_ty, #inner_ty> {
3218                                            rust_key_paths::lock::LockKp::new(
3219                                                rust_key_paths::Kp::new(
3220                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3221                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3222                                                ),
3223                                                rust_key_paths::lock::ParkingLotMutexAccess::new(),
3224                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3225                                            )
3226                                        }
3227                                    });
3228                                }
3229                                (WrapperKind::StdArcMutexOption, Some(inner_ty)) => {
3230                                    let snake_lock = format_ident!("{}_lock", snake);
3231                                    tokens.extend(quote! {
3232                                        #[inline(always)]
3233                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3234                                            rust_key_paths::Kp::new(
3235                                                |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3236                                                |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3237                                            )
3238                                        }
3239                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcMutexOptionFor<#name, #field_ty, #inner_ty> {
3240                                            rust_key_paths::lock::LockKp::new(
3241                                                rust_key_paths::Kp::new(
3242                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3243                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3244                                                ),
3245                                                rust_key_paths::lock::ArcMutexAccess::<Option<#inner_ty>>::new(),
3246                                                rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
3247                                            )
3248                                        }
3249                                    });
3250                                }
3251                                (WrapperKind::StdArcRwLockOption, Some(inner_ty)) => {
3252                                    let snake_lock = format_ident!("{}_lock", snake);
3253                                    tokens.extend(quote! {
3254                                        #[inline(always)]
3255                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3256                                            rust_key_paths::Kp::new(
3257                                                |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3258                                                |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3259                                            )
3260                                        }
3261                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcRwLockOptionFor<#name, #field_ty, #inner_ty> {
3262                                            rust_key_paths::lock::LockKp::new(
3263                                                rust_key_paths::Kp::new(
3264                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3265                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3266                                                ),
3267                                                rust_key_paths::lock::ArcRwLockAccess::<Option<#inner_ty>>::new(),
3268                                                rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
3269                                            )
3270                                        }
3271                                    });
3272                                }
3273                                (WrapperKind::ArcMutexOption, Some(inner_ty)) => {
3274                                    let snake_lock = format_ident!("{}_lock", snake);
3275                                    tokens.extend(quote! {
3276                                        #[inline(always)]
3277                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3278                                            rust_key_paths::Kp::new(
3279                                                |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3280                                                |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3281                                            )
3282                                        }
3283                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotMutexOptionFor<#name, #field_ty, #inner_ty> {
3284                                            rust_key_paths::lock::LockKp::new(
3285                                                rust_key_paths::Kp::new(
3286                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3287                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3288                                                ),
3289                                                rust_key_paths::lock::ParkingLotMutexAccess::<Option<#inner_ty>>::new(),
3290                                                rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
3291                                            )
3292                                        }
3293                                    });
3294                                }
3295                                (WrapperKind::ArcRwLockOption, Some(inner_ty)) => {
3296                                    let snake_lock = format_ident!("{}_lock", snake);
3297                                    tokens.extend(quote! {
3298                                        #[inline(always)]
3299                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3300                                            rust_key_paths::Kp::new(
3301                                                |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3302                                                |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3303                                            )
3304                                        }
3305                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotRwLockOptionFor<#name, #field_ty, #inner_ty> {
3306                                            rust_key_paths::lock::LockKp::new(
3307                                                rust_key_paths::Kp::new(
3308                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3309                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3310                                                ),
3311                                                rust_key_paths::lock::ParkingLotRwLockAccess::<Option<#inner_ty>>::new(),
3312                                                rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
3313                                            )
3314                                        }
3315                                    });
3316                                }
3317                                (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
3318                                    let snake_async = format_ident!("{}_kp", snake);
3319                                    tokens.extend(quote! {
3320                                        #[inline(always)]
3321                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3322                                            rust_key_paths::Kp::new(
3323                                                |root: &#name| match root {
3324                                                    #name::#v_ident(inner) => Some(inner),
3325                                                    _ => None,
3326                                                },
3327                                                |root: &mut #name| match root {
3328                                                    #name::#v_ident(inner) => Some(inner),
3329                                                    _ => None,
3330                                                },
3331                                            )
3332                                        }
3333                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #field_ty, #inner_ty> {
3334                                            rust_key_paths::async_lock::AsyncLockKp::new(
3335                                                rust_key_paths::Kp::new(
3336                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3337                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3338                                                ),
3339                                                rust_key_paths::async_lock::TokioMutexAccess::new(),
3340                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3341                                            )
3342                                        }
3343                                    });
3344                                }
3345                                (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
3346                                    let snake_async = format_ident!("{}_kp", snake);
3347                                    tokens.extend(quote! {
3348                                        #[inline(always)]
3349                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3350                                            rust_key_paths::Kp::new(
3351                                                |root: &#name| match root {
3352                                                    #name::#v_ident(inner) => Some(inner),
3353                                                    _ => None,
3354                                                },
3355                                                |root: &mut #name| match root {
3356                                                    #name::#v_ident(inner) => Some(inner),
3357                                                    _ => None,
3358                                                },
3359                                            )
3360                                        }
3361                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #field_ty, #inner_ty> {
3362                                            rust_key_paths::async_lock::AsyncLockKp::new(
3363                                                rust_key_paths::Kp::new(
3364                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3365                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3366                                                ),
3367                                                rust_key_paths::async_lock::TokioRwLockAccess::new(),
3368                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3369                                            )
3370                                        }
3371                                    });
3372                                }
3373                                (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
3374                                    let snake_async = format_ident!("{}_kp", snake);
3375                                    tokens.extend(quote! {
3376                                        #[inline(always)]
3377                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3378                                            rust_key_paths::Kp::new(
3379                                                |root: &#name| match root {
3380                                                    #name::#v_ident(inner) => Some(inner),
3381                                                    _ => None,
3382                                                },
3383                                                |root: &mut #name| match root {
3384                                                    #name::#v_ident(inner) => Some(inner),
3385                                                    _ => None,
3386                                                },
3387                                            )
3388                                        }
3389                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
3390                                            rust_key_paths::async_lock::AsyncLockKp::new(
3391                                                rust_key_paths::Kp::new(
3392                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3393                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3394                                                ),
3395                                                rust_key_paths::async_lock::TokioMutexAccess::new(),
3396                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3397                                            )
3398                                        }
3399                                    });
3400                                }
3401                                (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
3402                                    let snake_async = format_ident!("{}_kp", snake);
3403                                    tokens.extend(quote! {
3404                                        #[inline(always)]
3405                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3406                                            rust_key_paths::Kp::new(
3407                                                |root: &#name| match root {
3408                                                    #name::#v_ident(inner) => Some(inner),
3409                                                    _ => None,
3410                                                },
3411                                                |root: &mut #name| match root {
3412                                                    #name::#v_ident(inner) => Some(inner),
3413                                                    _ => None,
3414                                                },
3415                                            )
3416                                        }
3417                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
3418                                            rust_key_paths::async_lock::AsyncLockKp::new(
3419                                                rust_key_paths::Kp::new(
3420                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3421                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3422                                                ),
3423                                                rust_key_paths::async_lock::TokioRwLockAccess::new(),
3424                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3425                                            )
3426                                        }
3427                                    });
3428                                }
3429                                (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
3430                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3431                                    let snake_lock = format_ident!("{}_lock", snake);
3432                                    tokens.extend(quote! {
3433                                        #[inline(always)]
3434                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3435                                            rust_key_paths::Kp::new(
3436                                                |root: &#name| match root {
3437                                                    #name::#v_ident(inner) => Some(inner),
3438                                                    _ => None,
3439                                                },
3440                                                |root: &mut #name| match root {
3441                                                    #name::#v_ident(inner) => Some(inner),
3442                                                    _ => None,
3443                                                },
3444                                            )
3445                                        }
3446                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::Mutex<#inner_ty>>> {
3447                                            rust_key_paths::Kp::new(
3448                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3449                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3450                                            )
3451                                        }
3452                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcMutexFor<#name, std::sync::Arc<std::sync::Mutex<#inner_ty>>, #inner_ty> {
3453                                            rust_key_paths::lock::LockKp::new(
3454                                                rust_key_paths::Kp::new(
3455                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3456                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3457                                                ),
3458                                                rust_key_paths::lock::ArcMutexAccess::new(),
3459                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3460                                            )
3461                                        }
3462                                    });
3463                                }
3464                                (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
3465                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3466                                    let snake_lock = format_ident!("{}_lock", snake);
3467                                    tokens.extend(quote! {
3468                                        #[inline(always)]
3469                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3470                                            rust_key_paths::Kp::new(
3471                                                |root: &#name| match root {
3472                                                    #name::#v_ident(inner) => Some(inner),
3473                                                    _ => None,
3474                                                },
3475                                                |root: &mut #name| match root {
3476                                                    #name::#v_ident(inner) => Some(inner),
3477                                                    _ => None,
3478                                                },
3479                                            )
3480                                        }
3481                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>> {
3482                                            rust_key_paths::Kp::new(
3483                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3484                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3485                                            )
3486                                        }
3487                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>, #inner_ty> {
3488                                            rust_key_paths::lock::LockKp::new(
3489                                                rust_key_paths::Kp::new(
3490                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3491                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3492                                                ),
3493                                                rust_key_paths::lock::ParkingLotMutexAccess::new(),
3494                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3495                                            )
3496                                        }
3497                                    });
3498                                }
3499                                (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
3500                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3501                                    let snake_lock = format_ident!("{}_lock", snake);
3502                                    tokens.extend(quote! {
3503                                        #[inline(always)]
3504                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3505                                            rust_key_paths::Kp::new(
3506                                                |root: &#name| match root {
3507                                                    #name::#v_ident(inner) => Some(inner),
3508                                                    _ => None,
3509                                                },
3510                                                |root: &mut #name| match root {
3511                                                    #name::#v_ident(inner) => Some(inner),
3512                                                    _ => None,
3513                                                },
3514                                            )
3515                                        }
3516                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::RwLock<#inner_ty>>> {
3517                                            rust_key_paths::Kp::new(
3518                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3519                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3520                                            )
3521                                        }
3522                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, std::sync::Arc<std::sync::RwLock<#inner_ty>>, #inner_ty> {
3523                                            rust_key_paths::lock::LockKp::new(
3524                                                rust_key_paths::Kp::new(
3525                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3526                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3527                                                ),
3528                                                rust_key_paths::lock::ArcRwLockAccess::new(),
3529                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3530                                            )
3531                                        }
3532                                    });
3533                                }
3534                                (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
3535                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3536                                    let snake_lock = format_ident!("{}_lock", snake);
3537                                    tokens.extend(quote! {
3538                                        #[inline(always)]
3539                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3540                                            rust_key_paths::Kp::new(
3541                                                |root: &#name| match root {
3542                                                    #name::#v_ident(inner) => Some(inner),
3543                                                    _ => None,
3544                                                },
3545                                                |root: &mut #name| match root {
3546                                                    #name::#v_ident(inner) => Some(inner),
3547                                                    _ => None,
3548                                                },
3549                                            )
3550                                        }
3551                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>> {
3552                                            rust_key_paths::Kp::new(
3553                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3554                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3555                                            )
3556                                        }
3557                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>, #inner_ty> {
3558                                            rust_key_paths::lock::LockKp::new(
3559                                                rust_key_paths::Kp::new(
3560                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3561                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3562                                                ),
3563                                                rust_key_paths::lock::ParkingLotRwLockAccess::new(),
3564                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3565                                            )
3566                                        }
3567                                    });
3568                                }
3569                                (WrapperKind::StdMutex, Some(_inner_ty))
3570                                | (WrapperKind::Mutex, Some(_inner_ty))
3571                                | (WrapperKind::StdRwLock, Some(_inner_ty))
3572                                | (WrapperKind::RwLock, Some(_inner_ty)) => {
3573                                    tokens.extend(quote! {
3574                                        #[inline(always)]
3575                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3576                                            rust_key_paths::Kp::new(
3577                                                |root: &#name| match root {
3578                                                    #name::#v_ident(inner) => Some(inner),
3579                                                    _ => None,
3580                                                },
3581                                                |root: &mut #name| match root {
3582                                                    #name::#v_ident(inner) => Some(inner),
3583                                                    _ => None,
3584                                                },
3585                                            )
3586                                        }
3587                                    });
3588                                }
3589                                (WrapperKind::Tagged, Some(inner_ty)) => {
3590                                    tokens.extend(quote! {
3591                                        #[inline(always)]
3592                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3593                                            rust_key_paths::Kp::new(
3594                                                |root: &#name| match root {
3595                                                    #name::#v_ident(inner) => Some(std::ops::Deref::deref(inner)),
3596                                                    _ => None,
3597                                                },
3598                                                |root: &mut #name| match root {
3599                                                    #name::#v_ident(inner) => Some(std::ops::DerefMut::deref_mut(inner)),
3600                                                    _ => None,
3601                                                },
3602                                            )
3603                                        }
3604                                    });
3605                                }
3606                                (WrapperKind::Atomic, None | Some(_)) => {
3607                                    tokens.extend(quote! {
3608                                        #[inline(always)]
3609                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3610                                            rust_key_paths::Kp::new(
3611                                                |root: &#name| match root {
3612                                                    #name::#v_ident(inner) => Some(inner),
3613                                                    _ => None,
3614                                                },
3615                                                |root: &mut #name| match root {
3616                                                    #name::#v_ident(inner) => Some(inner),
3617                                                    _ => None,
3618                                                },
3619                                            )
3620                                        }
3621                                    });
3622                                }
3623                                (WrapperKind::OptionAtomic, Some(inner_ty)) => {
3624                                    tokens.extend(quote! {
3625                                        #[inline(always)]
3626                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3627                                            rust_key_paths::Kp::new(
3628                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3629                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3630                                            )
3631                                        }
3632                                    });
3633                                }
3634                                (WrapperKind::Reference, Some(_inner_ty)) => {
3635                                    tokens.extend(quote! {
3636                                        #[inline(always)]
3637                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3638                                            rust_key_paths::Kp::new(
3639                                                |root: &#name| match root {
3640                                                    #name::#v_ident(inner) => Some(inner),
3641                                                    _ => None,
3642                                                },
3643                                                |_root: &mut #name| None,
3644                                            )
3645                                        }
3646                                    });
3647                                }
3648                                (WrapperKind::Weak, Some(_inner_ty)) => {
3649                                    tokens.extend(quote! {
3650                                        #[inline(always)]
3651                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3652                                            rust_key_paths::Kp::new(
3653                                                |root: &#name| match root {
3654                                                    #name::#v_ident(inner) => Some(inner),
3655                                                    _ => None,
3656                                                },
3657                                                |_root: &mut #name| None,
3658                                            )
3659                                        }
3660                                    });
3661                                }
3662                                (WrapperKind::Cow, Some(inner_ty)) => {
3663                                    tokens.extend(quote! {
3664                                        #[inline(always)]
3665                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3666                                            rust_key_paths::Kp::new(
3667                                                |root: &#name| match root {
3668                                                    #name::#v_ident(inner) => Some(inner.as_ref()),
3669                                                    _ => None,
3670                                                },
3671                                                |root: &mut #name| match root {
3672                                                    #name::#v_ident(inner) => Some(inner.to_mut()),
3673                                                    _ => None,
3674                                                },
3675                                            )
3676                                        }
3677                                    });
3678                                }
3679                                (WrapperKind::OptionBox, Some(inner_ty)) => {
3680                                    // Option<Box<T>>: keypath to T via as_deref() / as_deref_mut()
3681                                    tokens.extend(quote! {
3682                                        #[inline(always)]
3683                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3684                                            rust_key_paths::Kp::new(
3685                                                |root: &#name| match root {
3686                                                    #name::#v_ident(inner) => inner.as_deref(),
3687                                                    _ => None,
3688                                                },
3689                                                |root: &mut #name| match root {
3690                                                    #name::#v_ident(inner) => inner.as_deref_mut(),
3691                                                    _ => None,
3692                                                },
3693                                            )
3694                                        }
3695                                    });
3696                                }
3697                                (WrapperKind::BoxOption, Some(inner_ty)) => {
3698                                    // Box<Option<T>>: keypath to T; inner is &Box<Option<T>>, deref then Option::as_ref/as_mut
3699                                    tokens.extend(quote! {
3700                                        #[inline(always)]
3701                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3702                                            rust_key_paths::Kp::new(
3703                                                |root: &#name| match root {
3704                                                    #name::#v_ident(inner) => (&*inner).as_ref(),
3705                                                    _ => None,
3706                                                },
3707                                                |root: &mut #name| match root {
3708                                                    #name::#v_ident(inner) => (&mut *inner).as_mut(),
3709                                                    _ => None,
3710                                                },
3711                                            )
3712                                        }
3713                                    });
3714                                }
3715                                (WrapperKind::RcOption, Some(inner_ty)) => {
3716                                    // Rc<Option<T>>: keypath to T; get = (&*inner).as_ref(), set = Rc::get_mut then as_mut
3717                                    tokens.extend(quote! {
3718                                        #[inline(always)]
3719                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3720                                            rust_key_paths::Kp::new(
3721                                                |root: &#name| match root {
3722                                                    #name::#v_ident(inner) => (&*inner).as_ref(),
3723                                                    _ => None,
3724                                                },
3725                                                |root: &mut #name| match root {
3726                                                    #name::#v_ident(inner) => std::rc::Rc::get_mut(inner).and_then(std::option::Option::as_mut),
3727                                                    _ => None,
3728                                                },
3729                                            )
3730                                        }
3731                                    });
3732                                }
3733                                (WrapperKind::ArcOption, Some(inner_ty)) => {
3734                                    // Arc<Option<T>>: keypath to T; get = (&*inner).as_ref(), set = Arc::get_mut then as_mut
3735                                    tokens.extend(quote! {
3736                                        #[inline(always)]
3737                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3738                                            rust_key_paths::Kp::new(
3739                                                |root: &#name| match root {
3740                                                    #name::#v_ident(inner) => (&*inner).as_ref(),
3741                                                    _ => None,
3742                                                },
3743                                                |root: &mut #name| match root {
3744                                                    #name::#v_ident(inner) => std::sync::Arc::get_mut(inner).and_then(std::option::Option::as_mut),
3745                                                    _ => None,
3746                                                },
3747                                            )
3748                                        }
3749                                    });
3750                                }
3751                                (WrapperKind::OptionRc, Some(inner_ty)) => {
3752                                    tokens.extend(quote! {
3753                                        #[inline(always)]
3754                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3755                                            rust_key_paths::Kp::new(
3756                                                |root: &#name| match root {
3757                                                    #name::#v_ident(inner) => inner.as_deref(),
3758                                                    _ => None,
3759                                                },
3760                                                |root: &mut #name| match root {
3761                                                    #name::#v_ident(inner) => inner.as_mut().and_then(std::rc::Rc::get_mut),
3762                                                    _ => None,
3763                                                },
3764                                            )
3765                                        }
3766                                    });
3767                                }
3768                                (WrapperKind::OptionArc, Some(inner_ty)) => {
3769                                    tokens.extend(quote! {
3770                                        #[inline(always)]
3771                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3772                                            rust_key_paths::Kp::new(
3773                                                |root: &#name| match root {
3774                                                    #name::#v_ident(inner) => inner.as_deref(),
3775                                                    _ => None,
3776                                                },
3777                                                |root: &mut #name| match root {
3778                                                    #name::#v_ident(inner) => inner.as_mut().and_then(std::sync::Arc::get_mut),
3779                                                    _ => None,
3780                                                },
3781                                            )
3782                                        }
3783                                    });
3784                                }
3785                                (WrapperKind::OptionCow, Some(inner_ty)) => {
3786                                    tokens.extend(quote! {
3787                                        #[inline(always)]
3788                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3789                                            rust_key_paths::Kp::new(
3790                                                |root: &#name| match root {
3791                                                    #name::#v_ident(inner) => inner.as_ref().map(|c| c.as_ref()),
3792                                                    _ => None,
3793                                                },
3794                                                |root: &mut #name| match root {
3795                                                    #name::#v_ident(inner) => inner.as_mut().map(|c| c.to_mut()),
3796                                                    _ => None,
3797                                                },
3798                                            )
3799                                        }
3800                                    });
3801                                }
3802                                (WrapperKind::OptionTagged, Some(inner_ty)) => {
3803                                    tokens.extend(quote! {
3804                                        #[inline(always)]
3805                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3806                                            rust_key_paths::Kp::new(
3807                                                |root: &#name| match root {
3808                                                    #name::#v_ident(inner) => inner.as_ref().map(|t| std::ops::Deref::deref(t)),
3809                                                    _ => None,
3810                                                },
3811                                                |root: &mut #name| match root {
3812                                                    #name::#v_ident(inner) => inner.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
3813                                                    _ => None,
3814                                                },
3815                                            )
3816                                        }
3817                                    });
3818                                }
3819                                (WrapperKind::OptionReference, Some(inner_ty)) => {
3820                                    tokens.extend(quote! {
3821                                        #[inline(always)]
3822                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3823                                            rust_key_paths::Kp::new(
3824                                                |root: &#name| match root {
3825                                                    #name::#v_ident(inner) => inner.as_ref(),
3826                                                    _ => None,
3827                                                },
3828                                                |_root: &mut #name| None,
3829                                            )
3830                                        }
3831                                    });
3832                                }
3833                                (WrapperKind::String, None) => {
3834                                    tokens.extend(quote! {
3835                                        #[inline(always)]
3836                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3837                                            rust_key_paths::Kp::new(
3838                                                |root: &#name| match root {
3839                                                    #name::#v_ident(inner) => Some(inner),
3840                                                    _ => None,
3841                                                },
3842                                                |root: &mut #name| match root {
3843                                                    #name::#v_ident(inner) => Some(inner),
3844                                                    _ => None,
3845                                                },
3846                                            )
3847                                        }
3848                                    });
3849                                }
3850                                (WrapperKind::OptionString, None) => {
3851                                    tokens.extend(quote! {
3852                                        #[inline(always)]
3853                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, std::string::String> {
3854                                            rust_key_paths::Kp::new(
3855                                                |root: &#name| match root {
3856                                                    #name::#v_ident(inner) => inner.as_ref(),
3857                                                    _ => None,
3858                                                },
3859                                                |root: &mut #name| match root {
3860                                                    #name::#v_ident(inner) => inner.as_mut(),
3861                                                    _ => None,
3862                                                },
3863                                            )
3864                                        }
3865                                    });
3866                                }
3867                                (WrapperKind::OnceCell, Some(inner_ty)) => {
3868                                    tokens.extend(quote! {
3869                                        #[inline(always)]
3870                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3871                                            rust_key_paths::Kp::new(
3872                                                |root: &#name| match root {
3873                                                    #name::#v_ident(inner) => inner.get(),
3874                                                    _ => None,
3875                                                },
3876                                                |_root: &mut #name| None,
3877                                            )
3878                                        }
3879                                    });
3880                                }
3881                                (WrapperKind::Lazy, Some(inner_ty)) => {
3882                                    tokens.extend(quote! {
3883                                        #[inline(always)]
3884                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3885                                            rust_key_paths::Kp::new(
3886                                                |root: &#name| match root {
3887                                                    #name::#v_ident(inner) => Some(inner.get()),
3888                                                    _ => None,
3889                                                },
3890                                                |_root: &mut #name| None,
3891                                            )
3892                                        }
3893                                    });
3894                                }
3895                                (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
3896                                    tokens.extend(quote! {
3897                                        #[inline(always)]
3898                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3899                                            rust_key_paths::Kp::new(
3900                                                |root: &#name| match root {
3901                                                    #name::#v_ident(inner) => inner.as_ref().and_then(|c| c.get()),
3902                                                    _ => None,
3903                                                },
3904                                                |_root: &mut #name| None,
3905                                            )
3906                                        }
3907                                    });
3908                                }
3909                                (WrapperKind::OptionLazy, Some(inner_ty)) => {
3910                                    tokens.extend(quote! {
3911                                        #[inline(always)]
3912                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3913                                            rust_key_paths::Kp::new(
3914                                                |root: &#name| match root {
3915                                                    #name::#v_ident(inner) => inner.as_ref().map(|c| c.get()),
3916                                                    _ => None,
3917                                                },
3918                                                |_root: &mut #name| None,
3919                                            )
3920                                        }
3921                                    });
3922                                }
3923                                (WrapperKind::Cell, Some(_inner_ty)) | (WrapperKind::RefCell, Some(_inner_ty))
3924                                | (WrapperKind::PhantomData, Some(_inner_ty)) | (WrapperKind::Range, Some(_inner_ty))
3925                                | (WrapperKind::OptionCell, Some(_inner_ty))
3926                                | (WrapperKind::OptionPhantomData, Some(_inner_ty)) | (WrapperKind::OptionRange, Some(_inner_ty)) => {
3927                                    tokens.extend(quote! {
3928                                        #[inline(always)]
3929                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3930                                            rust_key_paths::Kp::new(
3931                                                |root: &#name| match root {
3932                                                    #name::#v_ident(inner) => Some(inner),
3933                                                    _ => None,
3934                                                },
3935                                                |root: &mut #name| match root {
3936                                                    #name::#v_ident(inner) => Some(inner),
3937                                                    _ => None,
3938                                                },
3939                                            )
3940                                        }
3941                                    });
3942                                }
3943                                (WrapperKind::OptionRefCell, Some(inner_ty)) => {
3944                                    tokens.extend(quote! {
3945                                        #[inline(always)]
3946                                        pub fn #snake() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
3947                                            rust_key_paths::Kp::new(
3948                                                |root: &#name| match root {
3949                                                    #name::#v_ident(inner) => inner.as_ref().map(|r| r.borrow()),
3950                                                    _ => None,
3951                                                },
3952                                                |root: &mut #name| match root {
3953                                                    #name::#v_ident(inner) => inner.as_ref().map(|r| r.borrow_mut()),
3954                                                    _ => None,
3955                                                },
3956                                            )
3957                                        }
3958                                    });
3959                                }
3960                                (WrapperKind::None, None) => {
3961                                    // Basic type
3962                                    tokens.extend(quote! {
3963                                        #[inline(always)]
3964                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3965                                            rust_key_paths::Kp::new(
3966                                                |root: &#name| match root {
3967                                                    #name::#v_ident(inner) => Some(inner),
3968                                                    _ => None,
3969                                                },
3970                                                |root: &mut #name| match root {
3971                                                    #name::#v_ident(inner) => Some(inner),
3972                                                    _ => None,
3973                                                },
3974                                            )
3975                                        }
3976                                    });
3977                                }
3978                                _ => {
3979                                    // Other wrapper types - return keypath to field
3980                                    tokens.extend(quote! {
3981                                        #[inline(always)]
3982                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3983                                            rust_key_paths::Kp::new(
3984                                                |root: &#name| match root {
3985                                                    #name::#v_ident(inner) => Some(inner),
3986                                                    _ => None,
3987                                                },
3988                                                |root: &mut #name| match root {
3989                                                    #name::#v_ident(inner) => Some(inner),
3990                                                    _ => None,
3991                                                },
3992                                            )
3993                                        }
3994                                    });
3995                                }
3996                            }
3997                        } else {
3998                            // Multi-field tuple variant - return keypath to variant itself
3999                            tokens.extend(quote! {
4000                                #[inline(always)]
4001                                pub fn #snake() -> rust_key_paths::KpType<'static, #name, #name> {
4002                                    rust_key_paths::Kp::new(
4003                                        |root: &#name| match root {
4004                                            #name::#v_ident(..) => Some(root),
4005                                            _ => None,
4006                                        },
4007                                        |root: &mut #name| match root {
4008                                            #name::#v_ident(..) => Some(root),
4009                                            _ => None,
4010                                        },
4011                                    )
4012                                }
4013                            });
4014                        }
4015                    }
4016                    Fields::Named(_) => {
4017                        // Named field variant - return keypath to variant itself
4018                        tokens.extend(quote! {
4019                            pub fn #snake() -> rust_key_paths::KpType<'static, #name, #name> {
4020                                rust_key_paths::Kp::new(
4021                                    |root: &#name| match root {
4022                                        #name::#v_ident { .. } => Some(root),
4023                                        _ => None,
4024                                    },
4025                                    |root: &mut #name| match root {
4026                                        #name::#v_ident { .. } => Some(root),
4027                                        _ => None,
4028                                    },
4029                                )
4030                            }
4031                        });
4032                    }
4033                }
4034            }
4035
4036            tokens
4037        }
4038        Data::Union(_) => {
4039            return syn::Error::new(input_span, "Kp derive does not support unions")
4040            .to_compile_error()
4041            .into();
4042        }
4043    };
4044
4045    let expanded = quote! {
4046        impl #name {
4047            #methods
4048        }
4049    };
4050
4051    TokenStream::from(expanded)
4052}
4053
4054/// Derive macro that generates `partial_kps() -> Vec<PKp<Self>>` returning all field/variant keypaths.
4055/// **Requires `#[derive(Kp)]`** so the keypath accessor methods exist.
4056///
4057/// For structs: returns keypaths for each field. For enums: returns keypaths for each variant
4058/// (using the same methods Kp generates, e.g. `some_variant()`).
4059///
4060/// # Example
4061/// ```
4062/// use key_paths_derive::{Kp, Pkp};
4063/// use rust_key_paths::PKp;
4064///
4065/// #[derive(Kp, Pkp)]
4066/// struct Person {
4067///     name: String,
4068///     age: i32,
4069/// }
4070///
4071/// let kps = Person::partial_kps();
4072/// assert_eq!(kps.len(), 2);
4073/// ```
4074#[proc_macro_derive(Pkp)]
4075pub fn derive_partial_keypaths(input: TokenStream) -> TokenStream {
4076    let input = parse_macro_input!(input as DeriveInput);
4077    let name = &input.ident;
4078
4079    let kp_calls = match &input.data {
4080        Data::Struct(data_struct) => match &data_struct.fields {
4081            Fields::Named(fields_named) => {
4082                let calls: Vec<_> = fields_named
4083                    .named
4084                    .iter()
4085                    .filter_map(|f| f.ident.as_ref())
4086                    .map(|field_ident| {
4087                        quote! { rust_key_paths::PKp::new(Self::#field_ident()) }
4088                    })
4089                    .collect();
4090                quote! { #(#calls),* }
4091            }
4092            Fields::Unnamed(unnamed) => {
4093                let calls: Vec<_> = (0..unnamed.unnamed.len())
4094                    .map(|idx| {
4095                        let kp_fn = format_ident!("f{}", idx);
4096                        quote! { rust_key_paths::PKp::new(Self::#kp_fn()) }
4097                    })
4098                    .collect();
4099                quote! { #(#calls),* }
4100            }
4101            Fields::Unit => quote! {},
4102        },
4103        Data::Enum(data_enum) => {
4104            let calls: Vec<_> = data_enum
4105                .variants
4106                .iter()
4107                .map(|variant| {
4108                    let v_ident = &variant.ident;
4109                    let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
4110                    quote! { rust_key_paths::PKp::new(Self::#snake()) }
4111                })
4112                .collect();
4113            quote! { #(#calls),* }
4114        }
4115        Data::Union(_) => {
4116            return syn::Error::new(
4117                input.ident.span(),
4118                "Pkp derive does not support unions",
4119            )
4120            .to_compile_error()
4121            .into();
4122        }
4123    };
4124
4125    let expanded = quote! {
4126        impl #name {
4127            /// Returns a vec of all field keypaths as partial keypaths (type-erased).
4128            #[inline(always)]
4129            pub fn partial_kps() -> Vec<rust_key_paths::PKp<#name>> {
4130                vec![#kp_calls]
4131            }
4132        }
4133    };
4134
4135    TokenStream::from(expanded)
4136}
4137
4138/// Derive macro that generates `any_kps() -> Vec<AKp>` returning all field/variant keypaths as any keypaths.
4139/// **Requires `#[derive(Kp)]`** so the keypath accessor methods exist.
4140/// AKp type-erases both Root and Value, enabling heterogeneous collections of keypaths.
4141///
4142/// For structs: returns keypaths for each field. For enums: returns keypaths for each variant
4143/// (using the same methods Kp generates, e.g. `some_variant()`).
4144///
4145/// # Example
4146/// ```
4147/// use key_paths_derive::{Kp, Akp};
4148/// use rust_key_paths::AKp;
4149///
4150/// #[derive(Kp, Akp)]
4151/// struct Person {
4152///     name: String,
4153///     age: i32,
4154/// }
4155///
4156/// let kps = Person::any_kps();
4157/// assert_eq!(kps.len(), 2);
4158/// let person = Person { name: "Akash".into(), age: 30 };
4159/// let name: Option<&String> = kps[0].get(&person as &dyn std::any::Any).and_then(|v| v.downcast_ref());
4160/// assert_eq!(name, Some(&"Akash".to_string()));
4161/// ```
4162#[proc_macro_derive(Akp)]
4163pub fn derive_any_keypaths(input: TokenStream) -> TokenStream {
4164    let input = parse_macro_input!(input as DeriveInput);
4165    let name = &input.ident;
4166
4167    let kp_calls = match &input.data {
4168        Data::Struct(data_struct) => match &data_struct.fields {
4169            Fields::Named(fields_named) => {
4170                let calls: Vec<_> = fields_named
4171                    .named
4172                    .iter()
4173                    .filter_map(|f| f.ident.as_ref())
4174                    .map(|field_ident| {
4175                        quote! { rust_key_paths::AKp::new(Self::#field_ident()) }
4176                    })
4177                    .collect();
4178                quote! { #(#calls),* }
4179            }
4180            Fields::Unnamed(unnamed) => {
4181                let calls: Vec<_> = (0..unnamed.unnamed.len())
4182                    .map(|idx| {
4183                        let kp_fn = format_ident!("f{}", idx);
4184                        quote! { rust_key_paths::AKp::new(Self::#kp_fn()) }
4185                    })
4186                    .collect();
4187                quote! { #(#calls),* }
4188            }
4189            Fields::Unit => quote! {},
4190        },
4191        Data::Enum(data_enum) => {
4192            let calls: Vec<_> = data_enum
4193                .variants
4194                .iter()
4195                .map(|variant| {
4196                    let v_ident = &variant.ident;
4197                    let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
4198                    quote! { rust_key_paths::AKp::new(Self::#snake()) }
4199                })
4200                .collect();
4201            quote! { #(#calls),* }
4202        }
4203        Data::Union(_) => {
4204            return syn::Error::new(
4205                input.ident.span(),
4206                "Akp derive does not support unions",
4207            )
4208            .to_compile_error()
4209            .into();
4210        }
4211    };
4212
4213    let expanded = quote! {
4214        impl #name {
4215            /// Returns a vec of all field keypaths as any keypaths (fully type-erased).
4216            #[inline(always)]
4217            pub fn any_kps() -> Vec<rust_key_paths::AKp> {
4218                vec![#kp_calls]
4219            }
4220        }
4221    };
4222
4223    TokenStream::from(expanded)
4224}