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