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::OptionBox, Some(inner_ty)) => {
683                            // For Option<Box<T>>, keypath to T: get returns Option<&T> via as_deref()
684                            tokens.extend(quote! {
685                                #[inline(always)]
686                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
687                                    rust_key_paths::Kp::new(
688                                        |root: &#name| root.#field_ident.as_deref(),
689                                        |root: &mut #name| root.#field_ident.as_deref_mut(),
690                                    )
691                                }
692                            });
693                        }
694                        (WrapperKind::OptionRc, Some(inner_ty)) => {
695                            // For Option<Rc<T>>, keypath to T: get returns Option<&T> via as_deref()
696                            // Setter: as_mut() gives Option<&mut Rc<T>>, and_then(Rc::get_mut) gives Option<&mut T>
697                            tokens.extend(quote! {
698                                #[inline(always)]
699                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
700                                    rust_key_paths::Kp::new(
701                                        |root: &#name| root.#field_ident.as_deref(),
702                                        |root: &mut #name| root.#field_ident.as_mut().and_then(std::rc::Rc::get_mut),
703                                    )
704                                }
705                            });
706                        }
707                        (WrapperKind::OptionArc, Some(inner_ty)) => {
708                            // For Option<Arc<T>>, keypath to T: get returns Option<&T> via as_deref()
709                            // Setter: as_mut() gives Option<&mut Arc<T>>, and_then(Arc::get_mut) gives Option<&mut T>
710                            tokens.extend(quote! {
711                                #[inline(always)]
712                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
713                                    rust_key_paths::Kp::new(
714                                        |root: &#name| root.#field_ident.as_deref(),
715                                        |root: &mut #name| root.#field_ident.as_mut().and_then(std::sync::Arc::get_mut),
716                                    )
717                                }
718                            });
719                        }
720                        (WrapperKind::OptionVecDeque, Some(_inner_ty))
721                        | (WrapperKind::OptionLinkedList, Some(_inner_ty))
722                        | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
723                        | (WrapperKind::OptionHashSet, Some(_inner_ty))
724                        | (WrapperKind::OptionBTreeSet, Some(_inner_ty))
725                        | (WrapperKind::OptionResult, Some(_inner_ty))
726                        | (WrapperKind::OptionBTreeMap, Some(_inner_ty)) => {
727                            // Keypath to the Option container (reference), like Vec/HashSet
728                            tokens.extend(quote! {
729                                #[inline(always)]
730                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
731                                    rust_key_paths::Kp::new(
732                                        |root: &#name| Some(&root.#field_ident),
733                                        |root: &mut #name| Some(&mut root.#field_ident),
734                                    )
735                                }
736                            });
737                        }
738                        (WrapperKind::Vec, Some(inner_ty)) => {
739                            tokens.extend(quote! {
740                                #[inline(always)]
741                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
742                                    rust_key_paths::Kp::new(
743                                        |root: &#name| Some(&root.#field_ident),
744                                        |root: &mut #name| Some(&mut root.#field_ident),
745                                    )
746                                }
747                                #[inline(always)]
748                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
749                                    rust_key_paths::Kp::new(
750                                        Box::new(move |root: &#name| root.#field_ident.get(index)),
751                                        Box::new(move |root: &mut #name| root.#field_ident.get_mut(index)),
752                                    )
753                                }
754                            });
755                        }
756                        (WrapperKind::HashMap, Some(inner_ty)) => {
757                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
758                                tokens.extend(quote! {
759                                    #[inline(always)]
760                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
761                                        rust_key_paths::Kp::new(
762                                            |root: &#name| Some(&root.#field_ident),
763                                            |root: &mut #name| Some(&mut root.#field_ident),
764                                        )
765                                    }
766                                    #[inline(always)]
767                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
768                                    where
769                                        #key_ty: Clone + std::hash::Hash + Eq + 'static,
770                                    {
771                                        let key2 = key.clone();
772                                        rust_key_paths::Kp::new(
773                                            Box::new(move |root: &#name| root.#field_ident.get(&key)),
774                                            Box::new(move |root: &mut #name| root.#field_ident.get_mut(&key2)),
775                                        )
776                                    }
777                                });
778                            } else {
779                                tokens.extend(quote! {
780                                    #[inline(always)]
781                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
782                                        rust_key_paths::Kp::new(
783                                            |root: &#name| Some(&root.#field_ident),
784                                            |root: &mut #name| Some(&mut root.#field_ident),
785                                        )
786                                    }
787                                });
788                            }
789                        }
790                        (WrapperKind::BTreeMap, Some(inner_ty)) | (WrapperKind::BTreeMapOption, Some(inner_ty)) => {
791                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
792                                tokens.extend(quote! {
793                                    #[inline(always)]
794                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
795                                        rust_key_paths::Kp::new(
796                                            |root: &#name| Some(&root.#field_ident),
797                                            |root: &mut #name| Some(&mut root.#field_ident),
798                                        )
799                                    }
800                                    #[inline(always)]
801                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
802                                    where
803                                        #key_ty: Clone + Ord + 'static,
804                                    {
805                                        let key2 = key.clone();
806                                        rust_key_paths::Kp::new(
807                                            Box::new(move |root: &#name| root.#field_ident.get(&key)),
808                                            Box::new(move |root: &mut #name| root.#field_ident.get_mut(&key2)),
809                                        )
810                                    }
811                                });
812                            } else {
813                                tokens.extend(quote! {
814                                    #[inline(always)]
815                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
816                                        rust_key_paths::Kp::new(
817                                            |root: &#name| Some(&root.#field_ident),
818                                            |root: &mut #name| Some(&mut root.#field_ident),
819                                        )
820                                    }
821                                });
822                            }
823                        }
824                        (WrapperKind::Box, Some(inner_ty)) => {
825                            // For Box<T>, deref to inner type (returns &T / &mut T, not &Box<T>)
826                            tokens.extend(quote! {
827                                #[inline(always)]
828                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
829                                    rust_key_paths::Kp::new(
830                                        |root: &#name| Some(&*root.#field_ident),
831                                        |root: &mut #name| Some(&mut *root.#field_ident),
832                                    )
833                                }
834                            });
835                        }
836                        (WrapperKind::BoxOption, Some(inner_ty)) => {
837                            // For Box<Option<T>>, keypath to T: deref Box to Option<T>, then Option::as_ref/as_mut
838                            tokens.extend(quote! {
839                                #[inline(always)]
840                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
841                                    rust_key_paths::Kp::new(
842                                        |root: &#name| (&*root.#field_ident).as_ref(),
843                                        |root: &mut #name| (&mut *root.#field_ident).as_mut(),
844                                    )
845                                }
846                            });
847                        }
848                        (WrapperKind::RcOption, Some(inner_ty)) => {
849                            // For Rc<Option<T>>, keypath to T: deref Rc to &Option<T>, then Option::as_ref; set = Rc::get_mut then as_mut
850                            tokens.extend(quote! {
851                                #[inline(always)]
852                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
853                                    rust_key_paths::Kp::new(
854                                        |root: &#name| (&*root.#field_ident).as_ref(),
855                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#field_ident).and_then(std::option::Option::as_mut),
856                                    )
857                                }
858                            });
859                        }
860                        (WrapperKind::ArcOption, Some(inner_ty)) => {
861                            // For Arc<Option<T>>, keypath to T: deref Arc to &Option<T>, then Option::as_ref; set = Arc::get_mut then as_mut
862                            tokens.extend(quote! {
863                                #[inline(always)]
864                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
865                                    rust_key_paths::Kp::new(
866                                        |root: &#name| (&*root.#field_ident).as_ref(),
867                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#field_ident).and_then(std::option::Option::as_mut),
868                                    )
869                                }
870                            });
871                        }
872                        (WrapperKind::Pin, Some(inner_ty)) => {
873                            let kp_inner_fn = format_ident!("{}_inner", field_ident);
874                            tokens.extend(quote! {
875                                #[inline(always)]
876                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
877                                    rust_key_paths::Kp::new(
878                                        |root: &#name| Some(&root.#field_ident),
879                                        |root: &mut #name| Some(&mut root.#field_ident),
880                                    )
881                                }
882                                #[inline(always)]
883                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
884                                where #inner_ty: std::marker::Unpin
885                                {
886                                    rust_key_paths::Kp::new(
887                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#field_ident).get_ref()),
888                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#field_ident).get_mut()),
889                                    )
890                                }
891                            });
892                        }
893                        (WrapperKind::PinBox, Some(inner_ty)) => {
894                            let kp_inner_fn = format_ident!("{}_inner", field_ident);
895                            tokens.extend(quote! {
896                                #[inline(always)]
897                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
898                                    rust_key_paths::Kp::new(
899                                        |root: &#name| Some(&root.#field_ident),
900                                        |root: &mut #name| Some(&mut root.#field_ident),
901                                    )
902                                }
903                                #[inline(always)]
904                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
905                                where #inner_ty: std::marker::Unpin
906                                {
907                                    // Pin::as_ref on Pin<Box<T>> returns Pin<&T> (Box Deref target), so get_ref() already gives &T
908                                    rust_key_paths::Kp::new(
909                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#field_ident).get_ref()),
910                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#field_ident).get_mut()),
911                                    )
912                                }
913                            });
914                        }
915                        (WrapperKind::PinnedField, _) => {
916                            let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
917                            tokens.extend(quote! {
918                                #[inline(always)]
919                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
920                                    rust_key_paths::Kp::new(
921                                        |root: &#name| Some(&root.#field_ident),
922                                        |root: &mut #name| Some(&mut root.#field_ident),
923                                    )
924                                }
925                                /// Pinned projection for #[pin] field. Requires #[pin_project] on struct.
926                                #[inline(always)]
927                                pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
928                                    this.project().#field_ident
929                                }
930                            });
931                        }
932                        (WrapperKind::PinnedFuture, _) => {
933                            let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
934                            let kp_await_fn = format_ident!("{}_await", field_ident);
935                            let kp_pin_future_fn = format_ident!("{}_pin_future_kp", field_ident);
936                            let output_ty = quote! { <#ty as std::future::Future>::Output };
937                            tokens.extend(quote! {
938                                #[inline(always)]
939                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
940                                    rust_key_paths::Kp::new(
941                                        |root: &#name| Some(&root.#field_ident),
942                                        |root: &mut #name| Some(&mut root.#field_ident),
943                                    )
944                                }
945                                /// Pinned projection for #[pin] Future field. Requires #[pin_project] on struct.
946                                #[inline(always)]
947                                pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
948                                    this.project().#field_ident
949                                }
950                                /// Poll the pinned future. Requires #[pin_project] on struct.
951                                pub async fn #kp_await_fn(this: std::pin::Pin<&mut #name>) -> Option<#output_ty>
952                                where #ty: std::future::Future
953                                {
954                                    use std::future::Future;
955                                    Some(this.project().#field_ident.await)
956                                }
957                                /// Keypath for [rust_key_paths::Kp::then_pin_future]. Composable pin future await.
958                                #[inline(always)]
959                                pub fn #kp_pin_future_fn() -> impl rust_key_paths::pin::PinFutureAwaitLike<#name, #output_ty> {
960                                    rust_key_paths::pin_future_await_kp!(#name, #kp_await_fn -> #output_ty)
961                                }
962                            });
963                        }
964                        (WrapperKind::PinnedBoxFuture, Some(output_ty)) => {
965                            let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
966                            let kp_await_fn = format_ident!("{}_await", field_ident);
967                            let kp_pin_future_fn = format_ident!("{}_pin_future_kp", field_ident);
968                            tokens.extend(quote! {
969                                #[inline(always)]
970                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
971                                    rust_key_paths::Kp::new(
972                                        |root: &#name| Some(&root.#field_ident),
973                                        |root: &mut #name| Some(&mut root.#field_ident),
974                                    )
975                                }
976                                /// Pinned projection for #[pin] Box<dyn Future> field. Requires #[pin_project] on struct.
977                                #[inline(always)]
978                                pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
979                                    this.project().#field_ident
980                                }
981                                /// Poll the pinned boxed future. Requires #[pin_project] on struct.
982                                pub async fn #kp_await_fn(this: std::pin::Pin<&mut #name>) -> Option<#output_ty> {
983                                    Some(this.project().#field_ident.await)
984                                }
985                                /// Keypath for [rust_key_paths::Kp::then_pin_future]. Composable pin future await.
986                                #[inline(always)]
987                                pub fn #kp_pin_future_fn() -> impl rust_key_paths::pin::PinFutureAwaitLike<#name, #output_ty> {
988                                    rust_key_paths::pin_future_await_kp!(#name, #kp_await_fn -> #output_ty)
989                                }
990                            });
991                        }
992                        (WrapperKind::Rc, Some(inner_ty)) => {
993                            // For Rc<T>, deref to inner type (returns &T; get_mut when uniquely owned)
994                            tokens.extend(quote! {
995                                #[inline(always)]
996                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
997                                    rust_key_paths::Kp::new(
998                                        |root: &#name| Some(root.#field_ident.as_ref()),
999                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#field_ident),
1000                                    )
1001                                }
1002                            });
1003                        }
1004                        (WrapperKind::Arc, Some(inner_ty)) => {
1005                            // For Arc<T>, deref to inner type (returns &T; get_mut when uniquely owned)
1006                            tokens.extend(quote! {
1007                                #[inline(always)]
1008                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1009                                    rust_key_paths::Kp::new(
1010                                        |root: &#name| Some(root.#field_ident.as_ref()),
1011                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#field_ident),
1012                                    )
1013                                }
1014                            });
1015                        }
1016                        (WrapperKind::Cow, Some(inner_ty)) => {
1017                            // For Cow<'_, B>, deref to inner type (as_ref/to_mut)
1018                            tokens.extend(quote! {
1019                                #[inline(always)]
1020                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1021                                    rust_key_paths::Kp::new(
1022                                        |root: &#name| Some(root.#field_ident.as_ref()),
1023                                        |root: &mut #name| Some(root.#field_ident.to_mut()),
1024                                    )
1025                                }
1026                            });
1027                        }
1028                        
1029                        (WrapperKind::OptionCow, Some(inner_ty)) => {
1030                            // For Option<Cow<'_, B>>
1031                            tokens.extend(quote! {
1032                                #[inline(always)]
1033                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1034                                    rust_key_paths::Kp::new(
1035                                        |root: &#name| root.#field_ident.as_ref().map(|c| c.as_ref()),
1036                                        |root: &mut #name| root.#field_ident.as_mut().map(|c| c.to_mut()),
1037                                    )
1038                                }
1039                            });
1040                        }
1041                        (WrapperKind::OptionTagged, Some(inner_ty)) => {
1042                            // For Option<Tagged<Tag, T>> - Tagged implements Deref/DerefMut
1043                            tokens.extend(quote! {
1044                                #[inline(always)]
1045                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1046                                    rust_key_paths::Kp::new(
1047                                        |root: &#name| root.#field_ident.as_ref().map(|t| std::ops::Deref::deref(t)),
1048                                        |root: &mut #name| root.#field_ident.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
1049                                    )
1050                                }
1051                            });
1052                        }
1053                        (WrapperKind::OptionReference, Some(inner_ty)) => {
1054                            // For Option<&T>, Option<&str>, Option<&[T]> - read-only, setter returns None
1055                            tokens.extend(quote! {
1056                                #[inline(always)]
1057                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1058                                    rust_key_paths::Kp::new(
1059                                        |root: &#name| root.#field_ident.as_ref(),
1060                                        |_root: &mut #name| None,
1061                                    )
1062                                }
1063                            });
1064                        }
1065                        (WrapperKind::HashSet, Some(inner_ty)) | (WrapperKind::HashSetOption, Some(inner_ty)) => {
1066                            let kp_at_fn = format_ident!("{}_at", field_ident);
1067
1068                            tokens.extend(quote! {
1069                                #[inline(always)]
1070                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1071                                    rust_key_paths::Kp::new(
1072                                        |root: &#name| Some(&root.#field_ident),
1073                                        |root: &mut #name| Some(&mut root.#field_ident),
1074                                    )
1075                                }
1076
1077                                /// _at: check if element exists and get reference.
1078                                /// HashSet does not allow mutable element access (would break hash invariant).
1079                                #[inline(always)]
1080                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1081                                where
1082                                    #inner_ty: Clone + std::hash::Hash + Eq + 'static,
1083                                {
1084                                    rust_key_paths::Kp::new(
1085                                        Box::new(move |root: &#name| root.#field_ident.get(&key)),
1086                                        Box::new(move |_root: &mut #name| None),
1087                                    )
1088                                }
1089                            });
1090                        }
1091                        (WrapperKind::BTreeSet, Some(inner_ty)) | (WrapperKind::BTreeSetOption, Some(inner_ty)) => {
1092                            let kp_at_fn = format_ident!("{}_at", field_ident);
1093
1094                            tokens.extend(quote! {
1095                                #[inline(always)]
1096                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1097                                    rust_key_paths::Kp::new(
1098                                        |root: &#name| Some(&root.#field_ident),
1099                                        |root: &mut #name| Some(&mut root.#field_ident),
1100                                    )
1101                                }
1102
1103                                /// _at: check if element exists and get reference.
1104                                /// BTreeSet does not allow mutable element access (would break ordering invariant).
1105                                #[inline(always)]
1106                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1107                                where
1108                                    #inner_ty: Clone + Ord + 'static,
1109                                {
1110                                    rust_key_paths::Kp::new(
1111                                        Box::new(move |root: &#name| root.#field_ident.get(&key)),
1112                                        Box::new(move |_root: &mut #name| None),
1113                                    )
1114                                }
1115                            });
1116                        }
1117                        (WrapperKind::VecDeque, Some(inner_ty)) | (WrapperKind::VecDequeOption, Some(inner_ty)) => {
1118                            tokens.extend(quote! {
1119                                #[inline(always)]
1120                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1121                                    rust_key_paths::Kp::new(
1122                                        |root: &#name| Some(&root.#field_ident),
1123                                        |root: &mut #name| Some(&mut root.#field_ident),
1124                                    )
1125                                }
1126                                #[inline(always)]
1127                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
1128                                    rust_key_paths::Kp::new(
1129                                        Box::new(move |root: &#name| root.#field_ident.get(index)),
1130                                        Box::new(move |root: &mut #name| root.#field_ident.get_mut(index)),
1131                                    )
1132                                }
1133                            });
1134                        }
1135                        (WrapperKind::LinkedList, Some(_inner_ty)) | (WrapperKind::LinkedListOption, Some(_inner_ty)) => {
1136                            tokens.extend(quote! {
1137                                #[inline(always)]
1138                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1139                                    rust_key_paths::Kp::new(
1140                                        |root: &#name| Some(&root.#field_ident),
1141                                        |root: &mut #name| Some(&mut root.#field_ident),
1142                                    )
1143                                }
1144                            });
1145                        }
1146                        (WrapperKind::BinaryHeap, Some(_inner_ty)) | (WrapperKind::BinaryHeapOption, Some(_inner_ty)) => {
1147                            tokens.extend(quote! {
1148                                #[inline(always)]
1149                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1150                                    rust_key_paths::Kp::new(
1151                                        |root: &#name| Some(&root.#field_ident),
1152                                        |root: &mut #name| Some(&mut root.#field_ident),
1153                                    )
1154                                }
1155                            });
1156                        }
1157                        (WrapperKind::Result, Some(inner_ty)) => {
1158                            // For Result<T, E>, access Ok value
1159                            tokens.extend(quote! {
1160                                #[inline(always)]
1161                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1162                                    rust_key_paths::Kp::new(
1163                                        |root: &#name| root.#field_ident.as_ref().ok(),
1164                                        |root: &mut #name| root.#field_ident.as_mut().ok(),
1165                                    )
1166                                }
1167                            });
1168                        }
1169                        (WrapperKind::StdArcMutex, Some(inner_ty)) => {
1170                            // For Arc<std::sync::Mutex<T>>
1171                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1172                            tokens.extend(quote! {
1173                                #[inline(always)]
1174                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1175                                    rust_key_paths::Kp::new(
1176                                        |root: &#name| Some(&root.#field_ident),
1177                                        |root: &mut #name| Some(&mut root.#field_ident),
1178                                    )
1179                                }
1180                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcMutexFor<#name, #ty, #inner_ty> {
1181                                    rust_key_paths::lock::LockKp::new(
1182                                        rust_key_paths::Kp::new(
1183                                            |root: &#name| Some(&root.#field_ident),
1184                                            |root: &mut #name| Some(&mut root.#field_ident),
1185                                        ),
1186                                        rust_key_paths::lock::ArcMutexAccess::new(),
1187                                        rust_key_paths::Kp::new(
1188                                            |v: &#inner_ty| Some(v),
1189                                            |v: &mut #inner_ty| Some(v),
1190                                        ),
1191                                    )
1192                                }
1193                            });
1194                        }
1195                        (WrapperKind::StdArcRwLock, Some(inner_ty)) => {
1196                            // For Arc<std::sync::RwLock<T>>
1197                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1198                            tokens.extend(quote! {
1199                                #[inline(always)]
1200                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1201                                    rust_key_paths::Kp::new(
1202                                        |root: &#name| Some(&root.#field_ident),
1203                                        |root: &mut #name| Some(&mut root.#field_ident),
1204                                    )
1205                                }
1206                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, #ty, #inner_ty> {
1207                                    rust_key_paths::lock::LockKp::new(
1208                                        rust_key_paths::Kp::new(
1209                                            |root: &#name| Some(&root.#field_ident),
1210                                            |root: &mut #name| Some(&mut root.#field_ident),
1211                                        ),
1212                                        rust_key_paths::lock::ArcRwLockAccess::new(),
1213                                        rust_key_paths::Kp::new(
1214                                            |v: &#inner_ty| Some(v),
1215                                            |v: &mut #inner_ty| Some(v),
1216                                        ),
1217                                    )
1218                                }
1219                            });
1220                        }
1221                        (WrapperKind::ArcRwLock, Some(inner_ty)) => {
1222                            // For Arc<parking_lot::RwLock<T>> (requires rust-key-paths "parking_lot" feature)
1223                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1224                            tokens.extend(quote! {
1225                                #[inline(always)]
1226                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1227                                    rust_key_paths::Kp::new(
1228                                        |root: &#name| Some(&root.#field_ident),
1229                                        |root: &mut #name| Some(&mut root.#field_ident),
1230                                    )
1231                                }
1232                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, #ty, #inner_ty> {
1233                                    rust_key_paths::lock::LockKp::new(
1234                                        rust_key_paths::Kp::new(
1235                                            |root: &#name| Some(&root.#field_ident),
1236                                            |root: &mut #name| Some(&mut root.#field_ident),
1237                                        ),
1238                                        rust_key_paths::lock::ParkingLotRwLockAccess::new(),
1239                                        rust_key_paths::Kp::new(
1240                                            |v: &#inner_ty| Some(v),
1241                                            |v: &mut #inner_ty| Some(v),
1242                                        ),
1243                                    )
1244                                }
1245                            });
1246                        }
1247                        (WrapperKind::ArcMutex, Some(inner_ty)) => {
1248                            // For Arc<parking_lot::Mutex<T>> (requires rust-key-paths "parking_lot" feature)
1249                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1250                            tokens.extend(quote! {
1251                                #[inline(always)]
1252                                pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1253                                    rust_key_paths::Kp::new(
1254                                        |root: &#name| Some(&root.#field_ident),
1255                                        |root: &mut #name| Some(&mut root.#field_ident),
1256                                    )
1257                                }
1258                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, #ty, #inner_ty> {
1259                                    rust_key_paths::lock::LockKp::new(
1260                                        rust_key_paths::Kp::new(
1261                                            |root: &#name| Some(&root.#field_ident),
1262                                            |root: &mut #name| Some(&mut root.#field_ident),
1263                                        ),
1264                                        rust_key_paths::lock::ParkingLotMutexAccess::new(),
1265                                        rust_key_paths::Kp::new(
1266                                            |v: &#inner_ty| Some(v),
1267                                            |v: &mut #inner_ty| Some(v),
1268                                        ),
1269                                    )
1270                                }
1271                            });
1272                        }
1273                        (WrapperKind::Mutex, Some(_inner_ty))
1274                        | (WrapperKind::StdMutex, Some(_inner_ty)) => {
1275                            // For Mutex<T>, return keypath to container
1276                            tokens.extend(quote! {
1277                                #[inline(always)]
1278                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1279                                    rust_key_paths::Kp::new(
1280                                        |root: &#name| Some(&root.#field_ident),
1281                                        |root: &mut #name| Some(&mut root.#field_ident),
1282                                    )
1283                                }
1284                            });
1285                        }
1286                        (WrapperKind::RwLock, Some(_inner_ty))
1287                        | (WrapperKind::StdRwLock, Some(_inner_ty)) => {
1288                            // For RwLock<T>, return keypath to container
1289                            tokens.extend(quote! {
1290                                #[inline(always)]
1291                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1292                                    rust_key_paths::Kp::new(
1293                                        |root: &#name| Some(&root.#field_ident),
1294                                        |root: &mut #name| Some(&mut root.#field_ident),
1295                                    )
1296                                }
1297                            });
1298                        }
1299                        (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
1300                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1301                            tokens.extend(quote! {
1302                                #[inline(always)]
1303                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1304                                    rust_key_paths::Kp::new(
1305                                        |root: &#name| Some(&root.#field_ident),
1306                                        |root: &mut #name| Some(&mut root.#field_ident),
1307                                    )
1308                                }
1309                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #ty, #inner_ty> {
1310                                    rust_key_paths::async_lock::AsyncLockKp::new(
1311                                        rust_key_paths::Kp::new(
1312                                            |root: &#name| Some(&root.#field_ident),
1313                                            |root: &mut #name| Some(&mut root.#field_ident),
1314                                        ),
1315                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
1316                                        rust_key_paths::Kp::new(
1317                                            |v: &#inner_ty| Some(v),
1318                                            |v: &mut #inner_ty| Some(v),
1319                                        ),
1320                                    )
1321                                }
1322                            });
1323                        }
1324                        (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
1325                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1326                            tokens.extend(quote! {
1327                                #[inline(always)]
1328                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1329                                    rust_key_paths::Kp::new(
1330                                        |root: &#name| Some(&root.#field_ident),
1331                                        |root: &mut #name| Some(&mut root.#field_ident),
1332                                    )
1333                                }
1334                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #ty, #inner_ty> {
1335                                    rust_key_paths::async_lock::AsyncLockKp::new(
1336                                        rust_key_paths::Kp::new(
1337                                            |root: &#name| Some(&root.#field_ident),
1338                                            |root: &mut #name| Some(&mut root.#field_ident),
1339                                        ),
1340                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
1341                                        rust_key_paths::Kp::new(
1342                                            |v: &#inner_ty| Some(v),
1343                                            |v: &mut #inner_ty| Some(v),
1344                                        ),
1345                                    )
1346                                }
1347                            });
1348                        }
1349                        (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
1350                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1351                            tokens.extend(quote! {
1352                                #[inline(always)]
1353                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1354                                    rust_key_paths::Kp::new(
1355                                        |root: &#name| Some(&root.#field_ident),
1356                                        |root: &mut #name| Some(&mut root.#field_ident),
1357                                    )
1358                                }
1359                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
1360                                    rust_key_paths::async_lock::AsyncLockKp::new(
1361                                        rust_key_paths::Kp::new(
1362                                            |root: &#name| root.#field_ident.as_ref(),
1363                                            |root: &mut #name| root.#field_ident.as_mut(),
1364                                        ),
1365                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
1366                                        rust_key_paths::Kp::new(
1367                                            |v: &#inner_ty| Some(v),
1368                                            |v: &mut #inner_ty| Some(v),
1369                                        ),
1370                                    )
1371                                }
1372                            });
1373                        }
1374                        (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
1375                            let kp_async_fn = format_ident!("{}_kp", field_ident);
1376                            tokens.extend(quote! {
1377                                #[inline(always)]
1378                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1379                                    rust_key_paths::Kp::new(
1380                                        |root: &#name| Some(&root.#field_ident),
1381                                        |root: &mut #name| Some(&mut root.#field_ident),
1382                                    )
1383                                }
1384                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
1385                                    rust_key_paths::async_lock::AsyncLockKp::new(
1386                                        rust_key_paths::Kp::new(
1387                                            |root: &#name| root.#field_ident.as_ref(),
1388                                            |root: &mut #name| root.#field_ident.as_mut(),
1389                                        ),
1390                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
1391                                        rust_key_paths::Kp::new(
1392                                            |v: &#inner_ty| Some(v),
1393                                            |v: &mut #inner_ty| Some(v),
1394                                        ),
1395                                    )
1396                                }
1397                            });
1398                        }
1399                        (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
1400                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1401                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1402                            tokens.extend(quote! {
1403                                #[inline(always)]
1404                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1405                                    rust_key_paths::Kp::new(
1406                                        |root: &#name| Some(&root.#field_ident),
1407                                        |root: &mut #name| Some(&mut root.#field_ident),
1408                                    )
1409                                }
1410                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::Mutex<#inner_ty>>> {
1411                                //     rust_key_paths::Kp::new(
1412                                //         |root: &#name| root.#field_ident.as_ref(),
1413                                //         |root: &mut #name| root.#field_ident.as_mut(),
1414                                //     )
1415                                // }
1416                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcMutexFor<#name, std::sync::Arc<std::sync::Mutex<#inner_ty>>, #inner_ty> {
1417                                    rust_key_paths::lock::LockKp::new(
1418                                        rust_key_paths::Kp::new(
1419                                            |root: &#name| root.#field_ident.as_ref(),
1420                                            |root: &mut #name| root.#field_ident.as_mut(),
1421                                        ),
1422                                        rust_key_paths::lock::ArcMutexAccess::new(),
1423                                        rust_key_paths::Kp::new(
1424                                            |v: &#inner_ty| Some(v),
1425                                            |v: &mut #inner_ty| Some(v),
1426                                        ),
1427                                    )
1428                                }
1429                            });
1430                        }
1431                        (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
1432                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1433                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1434                            tokens.extend(quote! {
1435                                #[inline(always)]
1436                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1437                                    rust_key_paths::Kp::new(
1438                                        |root: &#name| Some(&root.#field_ident),
1439                                        |root: &mut #name| Some(&mut root.#field_ident),
1440                                    )
1441                                }
1442                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>> {
1443                                //     rust_key_paths::Kp::new(
1444                                //         |root: &#name| root.#field_ident.as_ref(),
1445                                //         |root: &mut #name| root.#field_ident.as_mut(),
1446                                //     )
1447                                // }
1448                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>, #inner_ty> {
1449                                    rust_key_paths::lock::LockKp::new(
1450                                        rust_key_paths::Kp::new(
1451                                            |root: &#name| root.#field_ident.as_ref(),
1452                                            |root: &mut #name| root.#field_ident.as_mut(),
1453                                        ),
1454                                        rust_key_paths::lock::ParkingLotMutexAccess::new(),
1455                                        rust_key_paths::Kp::new(
1456                                            |v: &#inner_ty| Some(v),
1457                                            |v: &mut #inner_ty| Some(v),
1458                                        ),
1459                                    )
1460                                }
1461                            });
1462                        }
1463                        (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
1464                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1465                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1466                            tokens.extend(quote! {
1467                                #[inline(always)]
1468                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1469                                    rust_key_paths::Kp::new(
1470                                        |root: &#name| Some(&root.#field_ident),
1471                                        |root: &mut #name| Some(&mut root.#field_ident),
1472                                    )
1473                                }
1474                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::RwLock<#inner_ty>>> {
1475                                //     rust_key_paths::Kp::new(
1476                                //         |root: &#name| root.#field_ident.as_ref(),
1477                                //         |root: &mut #name| root.#field_ident.as_mut(),
1478                                //     )
1479                                // }
1480                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, std::sync::Arc<std::sync::RwLock<#inner_ty>>, #inner_ty> {
1481                                    rust_key_paths::lock::LockKp::new(
1482                                        rust_key_paths::Kp::new(
1483                                            |root: &#name| root.#field_ident.as_ref(),
1484                                            |root: &mut #name| root.#field_ident.as_mut(),
1485                                        ),
1486                                        rust_key_paths::lock::ArcRwLockAccess::new(),
1487                                        rust_key_paths::Kp::new(
1488                                            |v: &#inner_ty| Some(v),
1489                                            |v: &mut #inner_ty| Some(v),
1490                                        ),
1491                                    )
1492                                }
1493                            });
1494                        }
1495                        (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
1496                            // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1497                            let kp_lock_fn = format_ident!("{}_kp", field_ident);
1498                            tokens.extend(quote! {
1499                                #[inline(always)]
1500                                    pub fn #kp_lock_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1501                                    rust_key_paths::Kp::new(
1502                                        |root: &#name| Some(&root.#field_ident),
1503                                        |root: &mut #name| Some(&mut root.#field_ident),
1504                                    )
1505                                }
1506                                // pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>> {
1507                                //     rust_key_paths::Kp::new(
1508                                //         |root: &#name| root.#field_ident.as_ref(),
1509                                //         |root: &mut #name| root.#field_ident.as_mut(),
1510                                //     )
1511                                // }
1512                                pub fn #kp_fn() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>, #inner_ty> {
1513                                    rust_key_paths::lock::LockKp::new(
1514                                        rust_key_paths::Kp::new(
1515                                            |root: &#name| root.#field_ident.as_ref(),
1516                                            |root: &mut #name| root.#field_ident.as_mut(),
1517                                        ),
1518                                        rust_key_paths::lock::ParkingLotRwLockAccess::new(),
1519                                        rust_key_paths::Kp::new(
1520                                            |v: &#inner_ty| Some(v),
1521                                            |v: &mut #inner_ty| Some(v),
1522                                        ),
1523                                    )
1524                                }
1525                            });
1526                        }
1527                        (WrapperKind::OptionStdMutex, Some(inner_ty))
1528                        | (WrapperKind::OptionMutex, Some(inner_ty)) => {
1529                            let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
1530                            tokens.extend(quote! {
1531                                #[inline(always)]
1532                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1533                                    rust_key_paths::Kp::new(
1534                                        |root: &#name| Some(&root.#field_ident),
1535                                        |root: &mut #name| Some(&mut root.#field_ident),
1536                                    )
1537                                }
1538                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Mutex<#inner_ty>> {
1539                                    rust_key_paths::Kp::new(
1540                                        |root: &#name| root.#field_ident.as_ref(),
1541                                        |root: &mut #name| root.#field_ident.as_mut(),
1542                                    )
1543                                }
1544                            });
1545                        }
1546                        (WrapperKind::OptionStdRwLock, Some(inner_ty))
1547                        | (WrapperKind::OptionRwLock, Some(inner_ty)) => {
1548                            let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
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                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::RwLock<#inner_ty>> {
1558                                    rust_key_paths::Kp::new(
1559                                        |root: &#name| root.#field_ident.as_ref(),
1560                                        |root: &mut #name| root.#field_ident.as_mut(),
1561                                    )
1562                                }
1563                            });
1564                        }
1565                        (WrapperKind::Weak, Some(_inner_ty)) => {
1566                            // For Weak<T>, return keypath to container
1567                            tokens.extend(quote! {
1568                                #[inline(always)]
1569                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1570                                    rust_key_paths::Kp::new(
1571                                        |root: &#name| Some(&root.#field_ident),
1572                                        |_root: &mut #name| None, // Weak doesn't support mutable access
1573                                    )
1574                                }
1575                            });
1576                        }
1577                        (WrapperKind::Atomic, None | Some(_)) => {
1578                            // For atomic types: return keypath to the atomic (user calls .load()/.store())
1579                            tokens.extend(quote! {
1580                                #[inline(always)]
1581                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1582                                    rust_key_paths::Kp::new(
1583                                        |root: &#name| Some(&root.#field_ident),
1584                                        |root: &mut #name| Some(&mut root.#field_ident),
1585                                    )
1586                                }
1587                            });
1588                        }
1589                        (WrapperKind::OptionAtomic, Some(inner_ty)) => {
1590                            tokens.extend(quote! {
1591                                #[inline(always)]
1592                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1593                                    rust_key_paths::Kp::new(
1594                                        |root: &#name| root.#field_ident.as_ref(),
1595                                        |root: &mut #name| root.#field_ident.as_mut(),
1596                                    )
1597                                }
1598                            });
1599                        }
1600                        (WrapperKind::String, None) => {
1601                            tokens.extend(quote! {
1602                                #[inline(always)]
1603                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1604                                    rust_key_paths::Kp::new(
1605                                        |root: &#name| Some(&root.#field_ident),
1606                                        |root: &mut #name| Some(&mut root.#field_ident),
1607                                    )
1608                                }
1609                            });
1610                        }
1611                        (WrapperKind::OptionString, None) => {
1612                            tokens.extend(quote! {
1613                                #[inline(always)]
1614                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, std::string::String> {
1615                                    rust_key_paths::Kp::new(
1616                                        |root: &#name| root.#field_ident.as_ref(),
1617                                        |root: &mut #name| root.#field_ident.as_mut(),
1618                                    )
1619                                }
1620                            });
1621                        }
1622                        (WrapperKind::Cell, Some(_inner_ty)) => {
1623                            tokens.extend(quote! {
1624                                #[inline(always)]
1625                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1626                                    rust_key_paths::Kp::new(
1627                                        |root: &#name| Some(&root.#field_ident),
1628                                        |root: &mut #name| Some(&mut root.#field_ident),
1629                                    )
1630                                }
1631                            });
1632                        }
1633                        (WrapperKind::RefCell, Some(_inner_ty)) => {
1634                            tokens.extend(quote! {
1635                                #[inline(always)]
1636                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1637                                    rust_key_paths::Kp::new(
1638                                        |root: &#name| Some(&root.#field_ident),
1639                                        |root: &mut #name| Some(&mut root.#field_ident),
1640                                    )
1641                                }
1642                            });
1643                        }
1644                        (WrapperKind::OnceCell, Some(inner_ty)) => {
1645                            // OnceLock/OnceCell: keypath to inner value; get = .get() -> Option<&T>, set = None
1646                            tokens.extend(quote! {
1647                                #[inline(always)]
1648                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1649                                    rust_key_paths::Kp::new(
1650                                        |root: &#name| root.#field_ident.get(),
1651                                        |_root: &mut #name| None,
1652                                    )
1653                                }
1654                            });
1655                        }
1656                        (WrapperKind::Lazy, Some(inner_ty)) => {
1657                            // Lazy/LazyLock: keypath to inner value; get = .get() -> &T wrapped in Some, set = None
1658                            tokens.extend(quote! {
1659                                #[inline(always)]
1660                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1661                                    rust_key_paths::Kp::new(
1662                                        |root: &#name| Some(root.#field_ident.get()),
1663                                        |_root: &mut #name| None,
1664                                    )
1665                                }
1666                            });
1667                        }
1668                        (WrapperKind::PhantomData, Some(_inner_ty)) => {
1669                            tokens.extend(quote! {
1670                                #[inline(always)]
1671                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1672                                    rust_key_paths::Kp::new(
1673                                        |root: &#name| Some(&root.#field_ident),
1674                                        |root: &mut #name| Some(&mut root.#field_ident),
1675                                    )
1676                                }
1677                            });
1678                        }
1679                        (WrapperKind::Range, Some(_inner_ty)) => {
1680                            tokens.extend(quote! {
1681                                #[inline(always)]
1682                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1683                                    rust_key_paths::Kp::new(
1684                                        |root: &#name| Some(&root.#field_ident),
1685                                        |root: &mut #name| Some(&mut root.#field_ident),
1686                                    )
1687                                }
1688                            });
1689                        }
1690                        (WrapperKind::OptionCell, Some(_inner_ty)) => {
1691                            tokens.extend(quote! {
1692                                #[inline(always)]
1693                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1694                                    rust_key_paths::Kp::new(
1695                                        |root: &#name| Some(&root.#field_ident),
1696                                        |root: &mut #name| Some(&mut root.#field_ident),
1697                                    )
1698                                }
1699                            });
1700                        }
1701                        (WrapperKind::OptionRefCell, Some(inner_ty)) => {
1702                            // Option<RefCell<T>>: keypath to T via borrow()/borrow_mut(); get returns Option<Ref<V>> so caller holds guard (deref for &V)
1703                            tokens.extend(quote! {
1704                                #[inline(always)]
1705                                pub fn #kp_fn() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
1706                                    rust_key_paths::Kp::new(
1707                                        |root: &#name| root.#field_ident.as_ref().map(|r| r.borrow()),
1708                                        |root: &mut #name| root.#field_ident.as_ref().map(|r| r.borrow_mut()),
1709                                    )
1710                                }
1711                            });
1712                        }
1713                        (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
1714                            tokens.extend(quote! {
1715                                #[inline(always)]
1716                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1717                                    rust_key_paths::Kp::new(
1718                                        |root: &#name| root.#field_ident.as_ref().and_then(|c| c.get()),
1719                                        |_root: &mut #name| None,
1720                                    )
1721                                }
1722                            });
1723                        }
1724                        (WrapperKind::OptionLazy, Some(inner_ty)) => {
1725                            tokens.extend(quote! {
1726                                #[inline(always)]
1727                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1728                                    rust_key_paths::Kp::new(
1729                                        |root: &#name| root.#field_ident.as_ref().map(|c| c.get()),
1730                                        |_root: &mut #name| None,
1731                                    )
1732                                }
1733                            });
1734                        }
1735                        (WrapperKind::OptionPhantomData, Some(_inner_ty)) => {
1736                            tokens.extend(quote! {
1737                                #[inline(always)]
1738                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1739                                    rust_key_paths::Kp::new(
1740                                        |root: &#name| Some(&root.#field_ident),
1741                                        |root: &mut #name| Some(&mut root.#field_ident),
1742                                    )
1743                                }
1744                            });
1745                        }
1746                        (WrapperKind::OptionRange, Some(_inner_ty)) => {
1747                            tokens.extend(quote! {
1748                                #[inline(always)]
1749                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1750                                    rust_key_paths::Kp::new(
1751                                        |root: &#name| Some(&root.#field_ident),
1752                                        |root: &mut #name| Some(&mut root.#field_ident),
1753                                    )
1754                                }
1755                            });
1756                        }
1757                        (WrapperKind::Reference, Some(_inner_ty)) => {
1758                            // For reference types (&T, &str, &[T]): read-only, setter returns None
1759                            tokens.extend(quote! {
1760                                #[inline(always)]
1761                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1762                                    rust_key_paths::Kp::new(
1763                                        |root: &#name| Some(&root.#field_ident),
1764                                        |_root: &mut #name| None, // references: read-only
1765                                    )
1766                                }
1767                            });
1768                        }
1769                        (WrapperKind::None, None) => {
1770                            // For basic types, direct access
1771                            tokens.extend(quote! {
1772                                #[inline(always)]
1773                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1774                                    rust_key_paths::Kp::new(
1775                                        |root: &#name| Some(&root.#field_ident),
1776                                        |root: &mut #name| Some(&mut root.#field_ident),
1777                                    )
1778                                }
1779                            });
1780                        }
1781                        _ => {
1782                            // For unknown/complex nested types, return keypath to field itself
1783                            tokens.extend(quote! {
1784                                #[inline(always)]
1785                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1786                            rust_key_paths::Kp::new(
1787                                |root: &#name| Some(&root.#field_ident),
1788                                |root: &mut #name| Some(&mut root.#field_ident),
1789                            )
1790                        }
1791                            });
1792                        }
1793                    }
1794                }
1795                
1796                tokens
1797            }
1798            Fields::Unnamed(unnamed) => {
1799                let mut tokens = proc_macro2::TokenStream::new();
1800
1801                // Generate identity methods for the tuple struct
1802                tokens.extend(quote! {
1803                    /// Returns a generic identity keypath for this type
1804                    #[inline(always)]
1805                    pub fn identity_typed<Root, MutRoot>() -> rust_key_paths::Kp<
1806                        #name,
1807                        #name,
1808                        Root,
1809                        Root,
1810                        MutRoot,
1811                        MutRoot,
1812                        fn(Root) -> Option<Root>,
1813                        fn(MutRoot) -> Option<MutRoot>,
1814                    >
1815                    where
1816                        Root: std::borrow::Borrow<#name>,
1817                        MutRoot: std::borrow::BorrowMut<#name>,
1818                    {
1819                        rust_key_paths::Kp::new(
1820                            |r: Root| Some(r),
1821                            |r: MutRoot| Some(r)
1822                        )
1823                    }
1824
1825                    /// Returns a simple identity keypath for this type
1826                    #[inline(always)]
1827                    pub fn identity() -> rust_key_paths::KpType<'static, #name, #name> {
1828                        rust_key_paths::Kp::new(
1829                            |r: &#name| Some(r),
1830                            |r: &mut #name| Some(r)
1831                        )
1832                    }
1833                });
1834
1835                for (idx, field) in unnamed.unnamed.iter().enumerate() {
1836                    let idx_lit = syn::Index::from(idx);
1837                    let ty = &field.ty;
1838                    // Centralized keypath method names for tuple fields – change here to adjust for all types
1839                    let kp_fn = format_ident!("f{}", idx);
1840                    let kp_at_fn = format_ident!("f{}_at", idx);
1841
1842                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1843
1844                    match (kind, inner_ty.clone()) {
1845                        (WrapperKind::Option, Some(inner_ty)) => {
1846                            tokens.extend(quote! {
1847                                #[inline(always)]
1848                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1849                                    rust_key_paths::Kp::new(
1850                                        |root: &#name| root.#idx_lit.as_ref(),
1851                                        |root: &mut #name| root.#idx_lit.as_mut(),
1852                                    )
1853                                }
1854                            });
1855                        }
1856                        (WrapperKind::OptionBox, Some(inner_ty)) => {
1857                            tokens.extend(quote! {
1858                                #[inline(always)]
1859                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1860                                    rust_key_paths::Kp::new(
1861                                        |root: &#name| root.#idx_lit.as_deref(),
1862                                        |root: &mut #name| root.#idx_lit.as_deref_mut(),
1863                                    )
1864                                }
1865                            });
1866                        }
1867                        (WrapperKind::OptionRc, Some(inner_ty)) => {
1868                            tokens.extend(quote! {
1869                                #[inline(always)]
1870                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1871                                    rust_key_paths::Kp::new(
1872                                        |root: &#name| root.#idx_lit.as_deref(),
1873                                        |root: &mut #name| root.#idx_lit.as_mut().and_then(std::rc::Rc::get_mut),
1874                                    )
1875                                }
1876                            });
1877                        }
1878                        (WrapperKind::OptionArc, Some(inner_ty)) => {
1879                            tokens.extend(quote! {
1880                                #[inline(always)]
1881                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1882                                    rust_key_paths::Kp::new(
1883                                        |root: &#name| root.#idx_lit.as_deref(),
1884                                        |root: &mut #name| root.#idx_lit.as_mut().and_then(std::sync::Arc::get_mut),
1885                                    )
1886                                }
1887                            });
1888                        }
1889                        (WrapperKind::OptionVecDeque, Some(_inner_ty))
1890                        | (WrapperKind::OptionLinkedList, Some(_inner_ty))
1891                        | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
1892                        | (WrapperKind::OptionHashSet, Some(_inner_ty))
1893                        | (WrapperKind::OptionBTreeSet, Some(_inner_ty))
1894                        | (WrapperKind::OptionResult, Some(_inner_ty))
1895                        | (WrapperKind::OptionBTreeMap, Some(_inner_ty)) => {
1896                            tokens.extend(quote! {
1897                                #[inline(always)]
1898                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1899                                    rust_key_paths::Kp::new(
1900                                        |root: &#name| Some(&root.#idx_lit),
1901                                        |root: &mut #name| Some(&mut root.#idx_lit),
1902                                    )
1903                                }
1904                            });
1905                        }
1906                        (WrapperKind::Vec, Some(inner_ty)) => {
1907                            tokens.extend(quote! {
1908                                #[inline(always)]
1909                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1910                                    rust_key_paths::Kp::new(
1911                                        |root: &#name| Some(&root.#idx_lit),
1912                                        |root: &mut #name| Some(&mut root.#idx_lit),
1913                                    )
1914                                }
1915                                #[inline(always)]
1916                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
1917                                    rust_key_paths::Kp::new(
1918                                        Box::new(move |root: &#name| root.#idx_lit.get(index)),
1919                                        Box::new(move |root: &mut #name| root.#idx_lit.get_mut(index)),
1920                                    )
1921                                }
1922                            });
1923                        }
1924                        (WrapperKind::HashMap, Some(inner_ty)) => {
1925                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
1926                                tokens.extend(quote! {
1927                                    #[inline(always)]
1928                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1929                                        rust_key_paths::Kp::new(
1930                                            |root: &#name| Some(&root.#idx_lit),
1931                                            |root: &mut #name| Some(&mut root.#idx_lit),
1932                                        )
1933                                    }
1934                                    #[inline(always)]
1935                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1936                                    where
1937                                        #key_ty: Clone + std::hash::Hash + Eq + 'static,
1938                                    {
1939                                        let key2 = key.clone();
1940                                        rust_key_paths::Kp::new(
1941                                            Box::new(move |root: &#name| root.#idx_lit.get(&key)),
1942                                            Box::new(move |root: &mut #name| root.#idx_lit.get_mut(&key2)),
1943                                        )
1944                                    }
1945                                });
1946                            } else {
1947                                tokens.extend(quote! {
1948                                    #[inline(always)]
1949                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1950                                        rust_key_paths::Kp::new(
1951                                            |root: &#name| Some(&root.#idx_lit),
1952                                            |root: &mut #name| Some(&mut root.#idx_lit),
1953                                        )
1954                                    }
1955                                });
1956                            }
1957                        }
1958                        (WrapperKind::BTreeMap, Some(inner_ty)) | (WrapperKind::BTreeMapOption, Some(inner_ty)) => {
1959                            if let Some((key_ty, _)) = extract_map_key_value(ty) {
1960                                tokens.extend(quote! {
1961                                    #[inline(always)]
1962                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1963                                        rust_key_paths::Kp::new(
1964                                            |root: &#name| Some(&root.#idx_lit),
1965                                            |root: &mut #name| Some(&mut root.#idx_lit),
1966                                        )
1967                                    }
1968                                    #[inline(always)]
1969                                    pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1970                                    where
1971                                        #key_ty: Clone + Ord + 'static,
1972                                    {
1973                                        let key2 = key.clone();
1974                                        rust_key_paths::Kp::new(
1975                                            Box::new(move |root: &#name| root.#idx_lit.get(&key)),
1976                                            Box::new(move |root: &mut #name| root.#idx_lit.get_mut(&key2)),
1977                                        )
1978                                    }
1979                                });
1980                            } else {
1981                                tokens.extend(quote! {
1982                                    #[inline(always)]
1983                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
1984                                        rust_key_paths::Kp::new(
1985                                            |root: &#name| Some(&root.#idx_lit),
1986                                            |root: &mut #name| Some(&mut root.#idx_lit),
1987                                        )
1988                                    }
1989                                });
1990                            }
1991                        }
1992                        (WrapperKind::Box, Some(inner_ty)) => {
1993                            // Box: deref to inner (returns &T / &mut T)
1994                            tokens.extend(quote! {
1995                                #[inline(always)]
1996                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
1997                                    rust_key_paths::Kp::new(
1998                                        |root: &#name| Some(&*root.#idx_lit),
1999                                        |root: &mut #name| Some(&mut *root.#idx_lit),
2000                                    )
2001                                }
2002                            });
2003                        }
2004                        (WrapperKind::BoxOption, Some(inner_ty)) => {
2005                            tokens.extend(quote! {
2006                                #[inline(always)]
2007                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2008                                    rust_key_paths::Kp::new(
2009                                        |root: &#name| (&*root.#idx_lit).as_ref(),
2010                                        |root: &mut #name| (&mut *root.#idx_lit).as_mut(),
2011                                    )
2012                                }
2013                            });
2014                        }
2015                        (WrapperKind::RcOption, Some(inner_ty)) => {
2016                            tokens.extend(quote! {
2017                                #[inline(always)]
2018                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2019                                    rust_key_paths::Kp::new(
2020                                        |root: &#name| (&*root.#idx_lit).as_ref(),
2021                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#idx_lit).and_then(std::option::Option::as_mut),
2022                                    )
2023                                }
2024                            });
2025                        }
2026                        (WrapperKind::ArcOption, Some(inner_ty)) => {
2027                            tokens.extend(quote! {
2028                                #[inline(always)]
2029                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2030                                    rust_key_paths::Kp::new(
2031                                        |root: &#name| (&*root.#idx_lit).as_ref(),
2032                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#idx_lit).and_then(std::option::Option::as_mut),
2033                                    )
2034                                }
2035                            });
2036                        }
2037                        (WrapperKind::Pin, Some(inner_ty)) => {
2038                            let kp_inner_fn = format_ident!("{}_inner", kp_fn);
2039                            tokens.extend(quote! {
2040                                #[inline(always)]
2041                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2042                                    rust_key_paths::Kp::new(
2043                                        |root: &#name| Some(&root.#idx_lit),
2044                                        |root: &mut #name| Some(&mut root.#idx_lit),
2045                                    )
2046                                }
2047                                #[inline(always)]
2048                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
2049                                where #inner_ty: std::marker::Unpin
2050                                {
2051                                    rust_key_paths::Kp::new(
2052                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#idx_lit).get_ref()),
2053                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#idx_lit).get_mut()),
2054                                    )
2055                                }
2056                            });
2057                        }
2058                        (WrapperKind::PinBox, Some(inner_ty)) => {
2059                            let kp_inner_fn = format_ident!("{}_inner", kp_fn);
2060                            tokens.extend(quote! {
2061                                #[inline(always)]
2062                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2063                                    rust_key_paths::Kp::new(
2064                                        |root: &#name| Some(&root.#idx_lit),
2065                                        |root: &mut #name| Some(&mut root.#idx_lit),
2066                                    )
2067                                }
2068                                #[inline(always)]
2069                                pub fn #kp_inner_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty>
2070                                where #inner_ty: std::marker::Unpin
2071                                {
2072                                    rust_key_paths::Kp::new(
2073                                        |root: &#name| Some(std::pin::Pin::as_ref(&root.#idx_lit).get_ref()),
2074                                        |root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#idx_lit).get_mut()),
2075                                    )
2076                                }
2077                            });
2078                        }
2079                        (WrapperKind::Rc, Some(inner_ty)) => {
2080                            tokens.extend(quote! {
2081                                #[inline(always)]
2082                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2083                                    rust_key_paths::Kp::new(
2084                                        |root: &#name| Some(root.#idx_lit.as_ref()),
2085                                        |root: &mut #name| std::rc::Rc::get_mut(&mut root.#idx_lit),
2086                                    )
2087                                }
2088                            });
2089                        }
2090                        (WrapperKind::Arc, Some(inner_ty)) => {
2091                            tokens.extend(quote! {
2092                                #[inline(always)]
2093                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2094                                    rust_key_paths::Kp::new(
2095                                        |root: &#name| Some(root.#idx_lit.as_ref()),
2096                                        |root: &mut #name| std::sync::Arc::get_mut(&mut root.#idx_lit),
2097                                    )
2098                                }
2099                            });
2100                        }
2101                        
2102                        (WrapperKind::Cow, Some(inner_ty)) => {
2103                            tokens.extend(quote! {
2104                                #[inline(always)]
2105                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2106                                    rust_key_paths::Kp::new(
2107                                        |root: &#name| Some(root.#idx_lit.as_ref()),
2108                                        |root: &mut #name| Some(root.#idx_lit.to_mut()),
2109                                    )
2110                                }
2111                            });
2112                        }
2113                        
2114                        (WrapperKind::OptionCow, Some(inner_ty)) => {
2115                            tokens.extend(quote! {
2116                                #[inline(always)]
2117                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2118                                    rust_key_paths::Kp::new(
2119                                        |root: &#name| root.#idx_lit.as_ref().map(|c| c.as_ref()),
2120                                        |root: &mut #name| root.#idx_lit.as_mut().map(|c| c.to_mut()),
2121                                    )
2122                                }
2123                            });
2124                        }
2125                        (WrapperKind::OptionTagged, Some(inner_ty)) => {
2126                            tokens.extend(quote! {
2127                                #[inline(always)]
2128                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2129                                    rust_key_paths::Kp::new(
2130                                        |root: &#name| root.#idx_lit.as_ref().map(|t| std::ops::Deref::deref(t)),
2131                                        |root: &mut #name| root.#idx_lit.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
2132                                    )
2133                                }
2134                            });
2135                        }
2136                        (WrapperKind::OptionReference, Some(inner_ty)) => {
2137                            tokens.extend(quote! {
2138                                #[inline(always)]
2139                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2140                                    rust_key_paths::Kp::new(
2141                                        |root: &#name| root.#idx_lit.as_ref(),
2142                                        |_root: &mut #name| None,
2143                                    )
2144                                }
2145                            });
2146                        }
2147                        (WrapperKind::HashSet, Some(inner_ty)) | (WrapperKind::HashSetOption, Some(inner_ty)) => {
2148                            let kp_at_fn = format_ident!("f{}_at", idx);
2149
2150                            tokens.extend(quote! {
2151                                #[inline(always)]
2152                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2153                                    rust_key_paths::Kp::new(
2154                                        |root: &#name| Some(&root.#idx_lit),
2155                                        |root: &mut #name| Some(&mut root.#idx_lit),
2156                                    )
2157                                }
2158
2159                                /// _at: check if element exists and get reference.
2160                                /// HashSet does not allow mutable element access (would break hash invariant).
2161                                #[inline(always)]
2162                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2163                                where
2164                                    #inner_ty: Clone + std::hash::Hash + Eq + 'static,
2165                                {
2166                                    rust_key_paths::Kp::new(
2167                                        Box::new(move |root: &#name| root.#idx_lit.get(&key)),
2168                                        Box::new(move |_root: &mut #name| None),
2169                                    )
2170                                }
2171                            });
2172                        }
2173                        (WrapperKind::BTreeSet, Some(inner_ty)) | (WrapperKind::BTreeSetOption, Some(inner_ty)) => {
2174                            let kp_at_fn = format_ident!("f{}_at", idx);
2175
2176                            tokens.extend(quote! {
2177                                #[inline(always)]
2178                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2179                                    rust_key_paths::Kp::new(
2180                                        |root: &#name| Some(&root.#idx_lit),
2181                                        |root: &mut #name| Some(&mut root.#idx_lit),
2182                                    )
2183                                }
2184
2185                                /// _at: check if element exists and get reference.
2186                                /// BTreeSet does not allow mutable element access (would break ordering invariant).
2187                                #[inline(always)]
2188                                pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2189                                where
2190                                    #inner_ty: Clone + Ord + 'static,
2191                                {
2192                                    rust_key_paths::Kp::new(
2193                                        Box::new(move |root: &#name| root.#idx_lit.get(&key)),
2194                                        Box::new(move |_root: &mut #name| None),
2195                                    )
2196                                }
2197                            });
2198                        }
2199                        (WrapperKind::VecDeque, Some(inner_ty)) | (WrapperKind::VecDequeOption, Some(inner_ty)) => {
2200                            tokens.extend(quote! {
2201                                #[inline(always)]
2202                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2203                                    rust_key_paths::Kp::new(
2204                                        |root: &#name| Some(&root.#idx_lit),
2205                                        |root: &mut #name| Some(&mut root.#idx_lit),
2206                                    )
2207                                }
2208                                #[inline(always)]
2209                                pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
2210                                    rust_key_paths::Kp::new(
2211                                        Box::new(move |root: &#name| root.#idx_lit.get(index)),
2212                                        Box::new(move |root: &mut #name| root.#idx_lit.get_mut(index)),
2213                                    )
2214                                }
2215                            });
2216                        }
2217                        (WrapperKind::LinkedList, Some(_inner_ty)) | (WrapperKind::LinkedListOption, Some(_inner_ty)) => {
2218                            tokens.extend(quote! {
2219                                #[inline(always)]
2220                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2221                                    rust_key_paths::Kp::new(
2222                                        |root: &#name| Some(&root.#idx_lit),
2223                                        |root: &mut #name| Some(&mut root.#idx_lit),
2224                                    )
2225                                }
2226                            });
2227                        }
2228                        (WrapperKind::BinaryHeap, Some(_inner_ty)) | (WrapperKind::BinaryHeapOption, Some(_inner_ty)) => {
2229                            tokens.extend(quote! {
2230                                #[inline(always)]
2231                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2232                                    rust_key_paths::Kp::new(
2233                                        |root: &#name| Some(&root.#idx_lit),
2234                                        |root: &mut #name| Some(&mut root.#idx_lit),
2235                                    )
2236                                }
2237                            });
2238                        }
2239                        (WrapperKind::Result, Some(inner_ty)) => {
2240                            tokens.extend(quote! {
2241                                #[inline(always)]
2242                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2243                                    rust_key_paths::Kp::new(
2244                                        |root: &#name| root.#idx_lit.as_ref().ok(),
2245                                        |root: &mut #name| root.#idx_lit.as_mut().ok(),
2246                                    )
2247                                }
2248                            });
2249                        }
2250                        (WrapperKind::Mutex, Some(_inner_ty))
2251                        | (WrapperKind::StdMutex, Some(_inner_ty)) => {
2252                            tokens.extend(quote! {
2253                                #[inline(always)]
2254                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2255                                    rust_key_paths::Kp::new(
2256                                        |root: &#name| Some(&root.#idx_lit),
2257                                        |root: &mut #name| Some(&mut root.#idx_lit),
2258                                    )
2259                                }
2260                            });
2261                        }
2262                        (WrapperKind::RwLock, Some(_inner_ty))
2263                        | (WrapperKind::StdRwLock, Some(_inner_ty)) => {
2264                            tokens.extend(quote! {
2265                                #[inline(always)]
2266                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2267                                    rust_key_paths::Kp::new(
2268                                        |root: &#name| Some(&root.#idx_lit),
2269                                        |root: &mut #name| Some(&mut root.#idx_lit),
2270                                    )
2271                                }
2272                            });
2273                        }
2274                        (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
2275                            let kp_async_fn = format_ident!("f{}_kp", idx);
2276                            tokens.extend(quote! {
2277                                #[inline(always)]
2278                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2279                                    rust_key_paths::Kp::new(
2280                                        |root: &#name| Some(&root.#idx_lit),
2281                                        |root: &mut #name| Some(&mut root.#idx_lit),
2282                                    )
2283                                }
2284                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #ty, #inner_ty> {
2285                                    rust_key_paths::async_lock::AsyncLockKp::new(
2286                                        rust_key_paths::Kp::new(
2287                                            |root: &#name| Some(&root.#idx_lit),
2288                                            |root: &mut #name| Some(&mut root.#idx_lit),
2289                                        ),
2290                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
2291                                        rust_key_paths::Kp::new(
2292                                            |v: &#inner_ty| Some(v),
2293                                            |v: &mut #inner_ty| Some(v),
2294                                        ),
2295                                    )
2296                                }
2297                            });
2298                        }
2299                        (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
2300                            let kp_async_fn = format_ident!("f{}_kp", idx);
2301                            tokens.extend(quote! {
2302                                #[inline(always)]
2303                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2304                                    rust_key_paths::Kp::new(
2305                                        |root: &#name| Some(&root.#idx_lit),
2306                                        |root: &mut #name| Some(&mut root.#idx_lit),
2307                                    )
2308                                }
2309                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #ty, #inner_ty> {
2310                                    rust_key_paths::async_lock::AsyncLockKp::new(
2311                                        rust_key_paths::Kp::new(
2312                                            |root: &#name| Some(&root.#idx_lit),
2313                                            |root: &mut #name| Some(&mut root.#idx_lit),
2314                                        ),
2315                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
2316                                        rust_key_paths::Kp::new(
2317                                            |v: &#inner_ty| Some(v),
2318                                            |v: &mut #inner_ty| Some(v),
2319                                        ),
2320                                    )
2321                                }
2322                            });
2323                        }
2324                        (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
2325                            let kp_async_fn = format_ident!("f{}_kp", idx);
2326                            tokens.extend(quote! {
2327                                #[inline(always)]
2328                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2329                                    rust_key_paths::Kp::new(
2330                                        |root: &#name| Some(&root.#idx_lit),
2331                                        |root: &mut #name| Some(&mut root.#idx_lit),
2332                                    )
2333                                }
2334                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
2335                                    rust_key_paths::async_lock::AsyncLockKp::new(
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                                        rust_key_paths::async_lock::TokioMutexAccess::new(),
2341                                        rust_key_paths::Kp::new(
2342                                            |v: &#inner_ty| Some(v),
2343                                            |v: &mut #inner_ty| Some(v),
2344                                        ),
2345                                    )
2346                                }
2347                            });
2348                        }
2349                        (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
2350                            let kp_async_fn = format_ident!("f{}_kp", idx);
2351                            tokens.extend(quote! {
2352                                #[inline(always)]
2353                                    pub fn #kp_async_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2354                                    rust_key_paths::Kp::new(
2355                                        |root: &#name| Some(&root.#idx_lit),
2356                                        |root: &mut #name| Some(&mut root.#idx_lit),
2357                                    )
2358                                }
2359                                pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
2360                                    rust_key_paths::async_lock::AsyncLockKp::new(
2361                                        rust_key_paths::Kp::new(
2362                                            |root: &#name| root.#idx_lit.as_ref(),
2363                                            |root: &mut #name| root.#idx_lit.as_mut(),
2364                                        ),
2365                                        rust_key_paths::async_lock::TokioRwLockAccess::new(),
2366                                        rust_key_paths::Kp::new(
2367                                            |v: &#inner_ty| Some(v),
2368                                            |v: &mut #inner_ty| Some(v),
2369                                        ),
2370                                    )
2371                                }
2372                            });
2373                        }
2374                        (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
2375                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2376                            tokens.extend(quote! {
2377                                #[inline(always)]
2378                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2379                                    rust_key_paths::Kp::new(
2380                                        |root: &#name| Some(&root.#idx_lit),
2381                                        |root: &mut #name| Some(&mut root.#idx_lit),
2382                                    )
2383                                }
2384                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::Mutex<#inner_ty>>> {
2385                                    rust_key_paths::Kp::new(
2386                                        |root: &#name| root.#idx_lit.as_ref(),
2387                                        |root: &mut #name| root.#idx_lit.as_mut(),
2388                                    )
2389                                }
2390                            });
2391                        }
2392                        (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
2393                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2394                            tokens.extend(quote! {
2395                                #[inline(always)]
2396                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2397                                    rust_key_paths::Kp::new(
2398                                        |root: &#name| Some(&root.#idx_lit),
2399                                        |root: &mut #name| Some(&mut root.#idx_lit),
2400                                    )
2401                                }
2402                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>> {
2403                                    rust_key_paths::Kp::new(
2404                                        |root: &#name| root.#idx_lit.as_ref(),
2405                                        |root: &mut #name| root.#idx_lit.as_mut(),
2406                                    )
2407                                }
2408                            });
2409                        }
2410                        (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
2411                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2412                            tokens.extend(quote! {
2413                                #[inline(always)]
2414                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2415                                    rust_key_paths::Kp::new(
2416                                        |root: &#name| Some(&root.#idx_lit),
2417                                        |root: &mut #name| Some(&mut root.#idx_lit),
2418                                    )
2419                                }
2420                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::RwLock<#inner_ty>>> {
2421                                    rust_key_paths::Kp::new(
2422                                        |root: &#name| root.#idx_lit.as_ref(),
2423                                        |root: &mut #name| root.#idx_lit.as_mut(),
2424                                    )
2425                                }
2426                            });
2427                        }
2428                        (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
2429                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2430                            tokens.extend(quote! {
2431                                #[inline(always)]
2432                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2433                                    rust_key_paths::Kp::new(
2434                                        |root: &#name| Some(&root.#idx_lit),
2435                                        |root: &mut #name| Some(&mut root.#idx_lit),
2436                                    )
2437                                }
2438                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>> {
2439                                    rust_key_paths::Kp::new(
2440                                        |root: &#name| root.#idx_lit.as_ref(),
2441                                        |root: &mut #name| root.#idx_lit.as_mut(),
2442                                    )
2443                                }
2444                            });
2445                        }
2446                        (WrapperKind::OptionStdMutex, Some(inner_ty))
2447                        | (WrapperKind::OptionMutex, Some(inner_ty)) => {
2448                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
2449                            tokens.extend(quote! {
2450                                #[inline(always)]
2451                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2452                                    rust_key_paths::Kp::new(
2453                                        |root: &#name| Some(&root.#idx_lit),
2454                                        |root: &mut #name| Some(&mut root.#idx_lit),
2455                                    )
2456                                }
2457                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::Mutex<#inner_ty>> {
2458                                    rust_key_paths::Kp::new(
2459                                        |root: &#name| root.#idx_lit.as_ref(),
2460                                        |root: &mut #name| root.#idx_lit.as_mut(),
2461                                    )
2462                                }
2463                            });
2464                        }
2465                        (WrapperKind::OptionStdRwLock, Some(inner_ty))
2466                        | (WrapperKind::OptionRwLock, Some(inner_ty)) => {
2467                            let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
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                                pub fn #kp_unlocked_fn() -> rust_key_paths::KpType<'static, #name, std::sync::RwLock<#inner_ty>> {
2477                                    rust_key_paths::Kp::new(
2478                                        |root: &#name| root.#idx_lit.as_ref(),
2479                                        |root: &mut #name| root.#idx_lit.as_mut(),
2480                                    )
2481                                }
2482                            });
2483                        }
2484                        (WrapperKind::Weak, Some(_inner_ty)) => {
2485                            tokens.extend(quote! {
2486                                #[inline(always)]
2487                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2488                                    rust_key_paths::Kp::new(
2489                                        |root: &#name| Some(&root.#idx_lit),
2490                                        |_root: &mut #name| None,
2491                                    )
2492                                }
2493                            });
2494                        }
2495                        (WrapperKind::Atomic, None | Some(_)) => {
2496                            tokens.extend(quote! {
2497                                #[inline(always)]
2498                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2499                                    rust_key_paths::Kp::new(
2500                                        |root: &#name| Some(&root.#idx_lit),
2501                                        |root: &mut #name| Some(&mut root.#idx_lit),
2502                                    )
2503                                }
2504                            });
2505                        }
2506                        (WrapperKind::OptionAtomic, Some(inner_ty)) => {
2507                            tokens.extend(quote! {
2508                                #[inline(always)]
2509                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2510                                    rust_key_paths::Kp::new(
2511                                        |root: &#name| root.#idx_lit.as_ref(),
2512                                        |root: &mut #name| root.#idx_lit.as_mut(),
2513                                    )
2514                                }
2515                            });
2516                        }
2517                        (WrapperKind::String, None) => {
2518                            tokens.extend(quote! {
2519                                #[inline(always)]
2520                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2521                                    rust_key_paths::Kp::new(
2522                                        |root: &#name| Some(&root.#idx_lit),
2523                                        |root: &mut #name| Some(&mut root.#idx_lit),
2524                                    )
2525                                }
2526                            });
2527                        }
2528                        (WrapperKind::OptionString, None) => {
2529                            tokens.extend(quote! {
2530                                #[inline(always)]
2531                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, std::string::String> {
2532                                    rust_key_paths::Kp::new(
2533                                        |root: &#name| root.#idx_lit.as_ref(),
2534                                        |root: &mut #name| root.#idx_lit.as_mut(),
2535                                    )
2536                                }
2537                            });
2538                        }
2539                        (WrapperKind::OnceCell, Some(inner_ty)) => {
2540                            tokens.extend(quote! {
2541                                #[inline(always)]
2542                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2543                                    rust_key_paths::Kp::new(
2544                                        |root: &#name| root.#idx_lit.get(),
2545                                        |_root: &mut #name| None,
2546                                    )
2547                                }
2548                            });
2549                        }
2550                        (WrapperKind::Lazy, Some(inner_ty)) => {
2551                            tokens.extend(quote! {
2552                                #[inline(always)]
2553                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2554                                    rust_key_paths::Kp::new(
2555                                        |root: &#name| Some(root.#idx_lit.get()),
2556                                        |_root: &mut #name| None,
2557                                    )
2558                                }
2559                            });
2560                        }
2561                        (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
2562                            tokens.extend(quote! {
2563                                #[inline(always)]
2564                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2565                                    rust_key_paths::Kp::new(
2566                                        |root: &#name| root.#idx_lit.as_ref().and_then(|c| c.get()),
2567                                        |_root: &mut #name| None,
2568                                    )
2569                                }
2570                            });
2571                        }
2572                        (WrapperKind::OptionLazy, Some(inner_ty)) => {
2573                            tokens.extend(quote! {
2574                                #[inline(always)]
2575                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2576                                    rust_key_paths::Kp::new(
2577                                        |root: &#name| root.#idx_lit.as_ref().map(|c| c.get()),
2578                                        |_root: &mut #name| None,
2579                                    )
2580                                }
2581                            });
2582                        }
2583                        (WrapperKind::Cell, Some(_inner_ty)) | (WrapperKind::RefCell, Some(_inner_ty))
2584                        | (WrapperKind::PhantomData, Some(_inner_ty)) | (WrapperKind::Range, Some(_inner_ty))
2585                        | (WrapperKind::OptionCell, Some(_inner_ty))
2586                        | (WrapperKind::OptionPhantomData, Some(_inner_ty)) | (WrapperKind::OptionRange, Some(_inner_ty)) => {
2587                            tokens.extend(quote! {
2588                                #[inline(always)]
2589                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2590                                    rust_key_paths::Kp::new(
2591                                        |root: &#name| Some(&root.#idx_lit),
2592                                        |root: &mut #name| Some(&mut root.#idx_lit),
2593                                    )
2594                                }
2595                            });
2596                        }
2597                        (WrapperKind::OptionRefCell, Some(inner_ty)) => {
2598                            tokens.extend(quote! {
2599                                #[inline(always)]
2600                                pub fn #kp_fn() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
2601                                    rust_key_paths::Kp::new(
2602                                        |root: &#name| root.#idx_lit.as_ref().map(|r| r.borrow()),
2603                                        |root: &mut #name| root.#idx_lit.as_ref().map(|r| r.borrow_mut()),
2604                                    )
2605                                }
2606                            });
2607                        }
2608                        (WrapperKind::Reference, Some(_inner_ty)) => {
2609                            tokens.extend(quote! {
2610                                #[inline(always)]
2611                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2612                                    rust_key_paths::Kp::new(
2613                                        |root: &#name| Some(&root.#idx_lit),
2614                                        |_root: &mut #name| None,
2615                                    )
2616                                }
2617                            });
2618                        }
2619                        (WrapperKind::None, None) => {
2620                            tokens.extend(quote! {
2621                                #[inline(always)]
2622                                pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2623                                    rust_key_paths::Kp::new(
2624                                        |root: &#name| Some(&root.#idx_lit),
2625                                        |root: &mut #name| Some(&mut root.#idx_lit),
2626                                    )
2627                                }
2628                            });
2629                        }
2630                        _ => {
2631                            tokens.extend(quote! {
2632                                #[inline(always)]
2633                                    pub fn #kp_fn() -> rust_key_paths::KpType<'static, #name, #ty> {
2634                                    rust_key_paths::Kp::new(
2635                                        |root: &#name| Some(&root.#idx_lit),
2636                                        |root: &mut #name| Some(&mut root.#idx_lit),
2637                                    )
2638                                }
2639                            });
2640                        }
2641                    }
2642                }
2643
2644                tokens
2645            }
2646            Fields::Unit => {
2647                return syn::Error::new(input_span, "Kp derive does not support unit structs")
2648                .to_compile_error()
2649                .into();
2650            }
2651        },
2652        Data::Enum(data_enum) => {
2653            let mut tokens = proc_macro2::TokenStream::new();
2654
2655            // Generate identity methods for the enum
2656            tokens.extend(quote! {
2657                /// Returns a generic identity keypath for this type
2658                #[inline(always)]
2659                pub fn identity_typed<Root, MutRoot>() -> rust_key_paths::Kp<
2660                    #name,
2661                    #name,
2662                    Root,
2663                    Root,
2664                    MutRoot,
2665                    MutRoot,
2666                    fn(Root) -> Option<Root>,
2667                    fn(MutRoot) -> Option<MutRoot>,
2668                >
2669                where
2670                    Root: std::borrow::Borrow<#name>,
2671                    MutRoot: std::borrow::BorrowMut<#name>,
2672                {
2673                    rust_key_paths::Kp::new(
2674                        |r: Root| Some(r),
2675                        |r: MutRoot| Some(r)
2676                    )
2677                }
2678
2679                /// Returns a simple identity keypath for this type
2680                #[inline(always)]
2681                pub fn identity() -> rust_key_paths::KpType<'static, #name, #name> {
2682                    rust_key_paths::Kp::new(
2683                        |r: &#name| Some(r),
2684                        |r: &mut #name| Some(r)
2685                    )
2686                }
2687            });
2688
2689            for variant in data_enum.variants.iter() {
2690                let v_ident = &variant.ident;
2691                let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
2692
2693                match &variant.fields {
2694                    Fields::Unit => {
2695                        // Unit variant - return keypath that checks if enum matches variant
2696                        tokens.extend(quote! {
2697                            #[inline(always)]
2698                            pub fn #snake() -> rust_key_paths::KpType<'static, #name, ()> {
2699                                rust_key_paths::Kp::new(
2700                                    |root: &#name| match root {
2701                                        #name::#v_ident => {
2702                                            static UNIT: () = ();
2703                                            Some(&UNIT)
2704                                        },
2705                                        _ => None,
2706                                    },
2707                                    |_root: &mut #name| None, // Can't mutate unit variant
2708                                )
2709                            }
2710                        });
2711                    }
2712                    Fields::Unnamed(unnamed) => {
2713                        if unnamed.unnamed.len() == 1 {
2714                            // Single-field tuple variant
2715                            let field_ty = &unnamed.unnamed[0].ty;
2716                            let (kind, inner_ty) = extract_wrapper_inner_type(field_ty);
2717
2718                            match (kind, inner_ty.clone()) {
2719                                (WrapperKind::Option, Some(inner_ty)) => {
2720                                    tokens.extend(quote! {
2721                                        #[inline(always)]
2722                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2723                                            rust_key_paths::Kp::new(
2724                                                |root: &#name| match root {
2725                                                    #name::#v_ident(inner) => inner.as_ref(),
2726                                                    _ => None,
2727                                                },
2728                                                |root: &mut #name| match root {
2729                                                    #name::#v_ident(inner) => inner.as_mut(),
2730                                                    _ => None,
2731                                                },
2732                                            )
2733                                        }
2734                                    });
2735                                }
2736                                (WrapperKind::OptionVecDeque, Some(_inner_ty))
2737                                | (WrapperKind::OptionLinkedList, Some(_inner_ty))
2738                                | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
2739                                | (WrapperKind::OptionHashSet, Some(_inner_ty))
2740                                | (WrapperKind::OptionBTreeSet, Some(_inner_ty))
2741                                | (WrapperKind::OptionResult, Some(_inner_ty))
2742                                | (WrapperKind::OptionBTreeMap, Some(_inner_ty)) => {
2743                                    tokens.extend(quote! {
2744                                        #[inline(always)]
2745                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2746                                            rust_key_paths::Kp::new(
2747                                                |root: &#name| match root {
2748                                                    #name::#v_ident(inner) => Some(inner),
2749                                                    _ => None,
2750                                                },
2751                                                |root: &mut #name| match root {
2752                                                    #name::#v_ident(inner) => Some(inner),
2753                                                    _ => None,
2754                                                },
2755                                            )
2756                                        }
2757                                    });
2758                                }
2759                                (WrapperKind::Vec, Some(inner_ty)) => {
2760                                    tokens.extend(quote! {
2761                                        #[inline(always)]
2762                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2763                                            rust_key_paths::Kp::new(
2764                                                |root: &#name| match root {
2765                                                    #name::#v_ident(inner) => inner.first(),
2766                                                    _ => None,
2767                                                },
2768                                                |root: &mut #name| match root {
2769                                                    #name::#v_ident(inner) => inner.first_mut(),
2770                                                    _ => None,
2771                                                },
2772                                            )
2773                                        }
2774                                    });
2775                                }
2776                                (WrapperKind::Box, Some(inner_ty)) => {
2777                                    // Box in enum: deref to inner (&T / &mut T)
2778                                    tokens.extend(quote! {
2779                                        #[inline(always)]
2780                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2781                                            rust_key_paths::Kp::new(
2782                                                |root: &#name| match root {
2783                                                    #name::#v_ident(inner) => Some(&**inner),
2784                                                    _ => None,
2785                                                },
2786                                                |root: &mut #name| match root {
2787                                                    #name::#v_ident(inner) => Some(&mut **inner),
2788                                                    _ => None,
2789                                                },
2790                                            )
2791                                        }
2792                                    });
2793                                }
2794                                (WrapperKind::Pin, Some(inner_ty)) => {
2795                                    let snake_inner = format_ident!("{}_inner", snake);
2796                                    tokens.extend(quote! {
2797                                        #[inline(always)]
2798                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2799                                            rust_key_paths::Kp::new(
2800                                                |root: &#name| match root {
2801                                                    #name::#v_ident(inner) => Some(inner),
2802                                                    _ => None,
2803                                                },
2804                                                |root: &mut #name| match root {
2805                                                    #name::#v_ident(inner) => Some(inner),
2806                                                    _ => None,
2807                                                },
2808                                            )
2809                                        }
2810                                        #[inline(always)]
2811                                        pub fn #snake_inner() -> rust_key_paths::KpType<'static, #name, #inner_ty>
2812                                        where #inner_ty: std::marker::Unpin
2813                                        {
2814                                            rust_key_paths::Kp::new(
2815                                                |root: &#name| match root {
2816                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_ref(inner).get_ref()),
2817                                                    _ => None,
2818                                                },
2819                                                |root: &mut #name| match root {
2820                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_mut(inner).get_mut()),
2821                                                    _ => None,
2822                                                },
2823                                            )
2824                                        }
2825                                    });
2826                                }
2827                                (WrapperKind::PinBox, Some(inner_ty)) => {
2828                                    let snake_inner = format_ident!("{}_inner", snake);
2829                                    tokens.extend(quote! {
2830                                        #[inline(always)]
2831                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2832                                            rust_key_paths::Kp::new(
2833                                                |root: &#name| match root {
2834                                                    #name::#v_ident(inner) => Some(inner),
2835                                                    _ => None,
2836                                                },
2837                                                |root: &mut #name| match root {
2838                                                    #name::#v_ident(inner) => Some(inner),
2839                                                    _ => None,
2840                                                },
2841                                            )
2842                                        }
2843                                        #[inline(always)]
2844                                        pub fn #snake_inner() -> rust_key_paths::KpType<'static, #name, #inner_ty>
2845                                        where #inner_ty: std::marker::Unpin
2846                                        {
2847                                            rust_key_paths::Kp::new(
2848                                                |root: &#name| match root {
2849                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_ref(inner).get_ref()),
2850                                                    _ => None,
2851                                                },
2852                                                |root: &mut #name| match root {
2853                                                    #name::#v_ident(inner) => Some(std::pin::Pin::as_mut(inner).get_mut()),
2854                                                    _ => None,
2855                                                },
2856                                            )
2857                                        }
2858                                    });
2859                                }
2860                                (WrapperKind::Rc, Some(inner_ty)) => {
2861                                    tokens.extend(quote! {
2862                                        #[inline(always)]
2863                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2864                                            rust_key_paths::Kp::new(
2865                                                |root: &#name| match root {
2866                                                    #name::#v_ident(inner) => Some(inner.as_ref()),
2867                                                    _ => None,
2868                                                },
2869                                                |root: &mut #name| match root {
2870                                                    #name::#v_ident(inner) => std::rc::Rc::get_mut(inner),
2871                                                    _ => None,
2872                                                },
2873                                            )
2874                                        }
2875                                    });
2876                                }
2877                                (WrapperKind::Arc, Some(inner_ty)) => {
2878                                    tokens.extend(quote! {
2879                                        #[inline(always)]
2880                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
2881                                            rust_key_paths::Kp::new(
2882                                                |root: &#name| match root {
2883                                                    #name::#v_ident(inner) => Some(inner.as_ref()),
2884                                                    _ => None,
2885                                                },
2886                                                |root: &mut #name| match root {
2887                                                    #name::#v_ident(inner) => std::sync::Arc::get_mut(inner),
2888                                                    _ => None,
2889                                                },
2890                                            )
2891                                        }
2892                                    });
2893                                }
2894                                (WrapperKind::StdArcRwLock, Some(inner_ty)) => {
2895                                    let snake_lock = format_ident!("{}_lock", snake);
2896                                    tokens.extend(quote! {
2897                                        #[inline(always)]
2898                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2899                                            rust_key_paths::Kp::new(
2900                                                |root: &#name| match root {
2901                                                    #name::#v_ident(inner) => Some(inner),
2902                                                    _ => None,
2903                                                },
2904                                                |root: &mut #name| match root {
2905                                                    #name::#v_ident(inner) => Some(inner),
2906                                                    _ => None,
2907                                                },
2908                                            )
2909                                        }
2910                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, #field_ty, #inner_ty> {
2911                                            rust_key_paths::lock::LockKp::new(
2912                                                rust_key_paths::Kp::new(
2913                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2914                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2915                                                ),
2916                                                rust_key_paths::lock::ArcRwLockAccess::new(),
2917                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
2918                                            )
2919                                        }
2920                                    });
2921                                }
2922                                (WrapperKind::StdArcMutex, Some(inner_ty)) => {
2923                                    let snake_lock = format_ident!("{}_lock", snake);
2924                                    tokens.extend(quote! {
2925                                        #[inline(always)]
2926                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2927                                            rust_key_paths::Kp::new(
2928                                                |root: &#name| match root {
2929                                                    #name::#v_ident(inner) => Some(inner),
2930                                                    _ => None,
2931                                                },
2932                                                |root: &mut #name| match root {
2933                                                    #name::#v_ident(inner) => Some(inner),
2934                                                    _ => None,
2935                                                },
2936                                            )
2937                                        }
2938                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcMutexFor<#name, #field_ty, #inner_ty> {
2939                                            rust_key_paths::lock::LockKp::new(
2940                                                rust_key_paths::Kp::new(
2941                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2942                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2943                                                ),
2944                                                rust_key_paths::lock::ArcMutexAccess::new(),
2945                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
2946                                            )
2947                                        }
2948                                    });
2949                                }
2950                                (WrapperKind::ArcRwLock, Some(inner_ty)) => {
2951                                    let snake_lock = format_ident!("{}_lock", snake);
2952                                    tokens.extend(quote! {
2953                                        #[inline(always)]
2954                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2955                                            rust_key_paths::Kp::new(
2956                                                |root: &#name| match root {
2957                                                    #name::#v_ident(inner) => Some(inner),
2958                                                    _ => None,
2959                                                },
2960                                                |root: &mut #name| match root {
2961                                                    #name::#v_ident(inner) => Some(inner),
2962                                                    _ => None,
2963                                                },
2964                                            )
2965                                        }
2966                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, #field_ty, #inner_ty> {
2967                                            rust_key_paths::lock::LockKp::new(
2968                                                rust_key_paths::Kp::new(
2969                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2970                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2971                                                ),
2972                                                rust_key_paths::lock::ParkingLotRwLockAccess::new(),
2973                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
2974                                            )
2975                                        }
2976                                    });
2977                                }
2978                                (WrapperKind::ArcMutex, Some(inner_ty)) => {
2979                                    let snake_lock = format_ident!("{}_lock", snake);
2980                                    tokens.extend(quote! {
2981                                        #[inline(always)]
2982                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
2983                                            rust_key_paths::Kp::new(
2984                                                |root: &#name| match root {
2985                                                    #name::#v_ident(inner) => Some(inner),
2986                                                    _ => None,
2987                                                },
2988                                                |root: &mut #name| match root {
2989                                                    #name::#v_ident(inner) => Some(inner),
2990                                                    _ => None,
2991                                                },
2992                                            )
2993                                        }
2994                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, #field_ty, #inner_ty> {
2995                                            rust_key_paths::lock::LockKp::new(
2996                                                rust_key_paths::Kp::new(
2997                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2998                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
2999                                                ),
3000                                                rust_key_paths::lock::ParkingLotMutexAccess::new(),
3001                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3002                                            )
3003                                        }
3004                                    });
3005                                }
3006                                (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
3007                                    let snake_async = format_ident!("{}_kp", snake);
3008                                    tokens.extend(quote! {
3009                                        #[inline(always)]
3010                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3011                                            rust_key_paths::Kp::new(
3012                                                |root: &#name| match root {
3013                                                    #name::#v_ident(inner) => Some(inner),
3014                                                    _ => None,
3015                                                },
3016                                                |root: &mut #name| match root {
3017                                                    #name::#v_ident(inner) => Some(inner),
3018                                                    _ => None,
3019                                                },
3020                                            )
3021                                        }
3022                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #field_ty, #inner_ty> {
3023                                            rust_key_paths::async_lock::AsyncLockKp::new(
3024                                                rust_key_paths::Kp::new(
3025                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3026                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3027                                                ),
3028                                                rust_key_paths::async_lock::TokioMutexAccess::new(),
3029                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3030                                            )
3031                                        }
3032                                    });
3033                                }
3034                                (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
3035                                    let snake_async = format_ident!("{}_kp", snake);
3036                                    tokens.extend(quote! {
3037                                        #[inline(always)]
3038                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3039                                            rust_key_paths::Kp::new(
3040                                                |root: &#name| match root {
3041                                                    #name::#v_ident(inner) => Some(inner),
3042                                                    _ => None,
3043                                                },
3044                                                |root: &mut #name| match root {
3045                                                    #name::#v_ident(inner) => Some(inner),
3046                                                    _ => None,
3047                                                },
3048                                            )
3049                                        }
3050                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #field_ty, #inner_ty> {
3051                                            rust_key_paths::async_lock::AsyncLockKp::new(
3052                                                rust_key_paths::Kp::new(
3053                                                    |root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3054                                                    |root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None },
3055                                                ),
3056                                                rust_key_paths::async_lock::TokioRwLockAccess::new(),
3057                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3058                                            )
3059                                        }
3060                                    });
3061                                }
3062                                (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
3063                                    let snake_async = format_ident!("{}_kp", snake);
3064                                    tokens.extend(quote! {
3065                                        #[inline(always)]
3066                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3067                                            rust_key_paths::Kp::new(
3068                                                |root: &#name| match root {
3069                                                    #name::#v_ident(inner) => Some(inner),
3070                                                    _ => None,
3071                                                },
3072                                                |root: &mut #name| match root {
3073                                                    #name::#v_ident(inner) => Some(inner),
3074                                                    _ => None,
3075                                                },
3076                                            )
3077                                        }
3078                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
3079                                            rust_key_paths::async_lock::AsyncLockKp::new(
3080                                                rust_key_paths::Kp::new(
3081                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3082                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3083                                                ),
3084                                                rust_key_paths::async_lock::TokioMutexAccess::new(),
3085                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3086                                            )
3087                                        }
3088                                    });
3089                                }
3090                                (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
3091                                    let snake_async = format_ident!("{}_kp", snake);
3092                                    tokens.extend(quote! {
3093                                        #[inline(always)]
3094                                        pub fn #snake_async() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3095                                            rust_key_paths::Kp::new(
3096                                                |root: &#name| match root {
3097                                                    #name::#v_ident(inner) => Some(inner),
3098                                                    _ => None,
3099                                                },
3100                                                |root: &mut #name| match root {
3101                                                    #name::#v_ident(inner) => Some(inner),
3102                                                    _ => None,
3103                                                },
3104                                            )
3105                                        }
3106                                        pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
3107                                            rust_key_paths::async_lock::AsyncLockKp::new(
3108                                                rust_key_paths::Kp::new(
3109                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3110                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3111                                                ),
3112                                                rust_key_paths::async_lock::TokioRwLockAccess::new(),
3113                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3114                                            )
3115                                        }
3116                                    });
3117                                }
3118                                (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
3119                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3120                                    let snake_lock = format_ident!("{}_lock", snake);
3121                                    tokens.extend(quote! {
3122                                        #[inline(always)]
3123                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3124                                            rust_key_paths::Kp::new(
3125                                                |root: &#name| match root {
3126                                                    #name::#v_ident(inner) => Some(inner),
3127                                                    _ => None,
3128                                                },
3129                                                |root: &mut #name| match root {
3130                                                    #name::#v_ident(inner) => Some(inner),
3131                                                    _ => None,
3132                                                },
3133                                            )
3134                                        }
3135                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::Mutex<#inner_ty>>> {
3136                                            rust_key_paths::Kp::new(
3137                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3138                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3139                                            )
3140                                        }
3141                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcMutexFor<#name, std::sync::Arc<std::sync::Mutex<#inner_ty>>, #inner_ty> {
3142                                            rust_key_paths::lock::LockKp::new(
3143                                                rust_key_paths::Kp::new(
3144                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3145                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3146                                                ),
3147                                                rust_key_paths::lock::ArcMutexAccess::new(),
3148                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3149                                            )
3150                                        }
3151                                    });
3152                                }
3153                                (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
3154                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3155                                    let snake_lock = format_ident!("{}_lock", snake);
3156                                    tokens.extend(quote! {
3157                                        #[inline(always)]
3158                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3159                                            rust_key_paths::Kp::new(
3160                                                |root: &#name| match root {
3161                                                    #name::#v_ident(inner) => Some(inner),
3162                                                    _ => None,
3163                                                },
3164                                                |root: &mut #name| match root {
3165                                                    #name::#v_ident(inner) => Some(inner),
3166                                                    _ => None,
3167                                                },
3168                                            )
3169                                        }
3170                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>> {
3171                                            rust_key_paths::Kp::new(
3172                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3173                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3174                                            )
3175                                        }
3176                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotMutexFor<#name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>, #inner_ty> {
3177                                            rust_key_paths::lock::LockKp::new(
3178                                                rust_key_paths::Kp::new(
3179                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3180                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3181                                                ),
3182                                                rust_key_paths::lock::ParkingLotMutexAccess::new(),
3183                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3184                                            )
3185                                        }
3186                                    });
3187                                }
3188                                (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
3189                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3190                                    let snake_lock = format_ident!("{}_lock", snake);
3191                                    tokens.extend(quote! {
3192                                        #[inline(always)]
3193                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3194                                            rust_key_paths::Kp::new(
3195                                                |root: &#name| match root {
3196                                                    #name::#v_ident(inner) => Some(inner),
3197                                                    _ => None,
3198                                                },
3199                                                |root: &mut #name| match root {
3200                                                    #name::#v_ident(inner) => Some(inner),
3201                                                    _ => None,
3202                                                },
3203                                            )
3204                                        }
3205                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<std::sync::RwLock<#inner_ty>>> {
3206                                            rust_key_paths::Kp::new(
3207                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3208                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3209                                            )
3210                                        }
3211                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpArcRwLockFor<#name, std::sync::Arc<std::sync::RwLock<#inner_ty>>, #inner_ty> {
3212                                            rust_key_paths::lock::LockKp::new(
3213                                                rust_key_paths::Kp::new(
3214                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3215                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3216                                                ),
3217                                                rust_key_paths::lock::ArcRwLockAccess::new(),
3218                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3219                                            )
3220                                        }
3221                                    });
3222                                }
3223                                (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
3224                                    let snake_unlocked = format_ident!("{}_unlocked", snake);
3225                                    let snake_lock = format_ident!("{}_lock", snake);
3226                                    tokens.extend(quote! {
3227                                        #[inline(always)]
3228                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3229                                            rust_key_paths::Kp::new(
3230                                                |root: &#name| match root {
3231                                                    #name::#v_ident(inner) => Some(inner),
3232                                                    _ => None,
3233                                                },
3234                                                |root: &mut #name| match root {
3235                                                    #name::#v_ident(inner) => Some(inner),
3236                                                    _ => None,
3237                                                },
3238                                            )
3239                                        }
3240                                        pub fn #snake_unlocked() -> rust_key_paths::KpType<'static, #name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>> {
3241                                            rust_key_paths::Kp::new(
3242                                                |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3243                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3244                                            )
3245                                        }
3246                                        pub fn #snake_lock() -> rust_key_paths::lock::LockKpParkingLotRwLockFor<#name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>, #inner_ty> {
3247                                            rust_key_paths::lock::LockKp::new(
3248                                                rust_key_paths::Kp::new(
3249                                                    |root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3250                                                    |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3251                                                ),
3252                                                rust_key_paths::lock::ParkingLotRwLockAccess::new(),
3253                                                rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
3254                                            )
3255                                        }
3256                                    });
3257                                }
3258                                (WrapperKind::StdMutex, Some(_inner_ty))
3259                                | (WrapperKind::Mutex, Some(_inner_ty))
3260                                | (WrapperKind::StdRwLock, Some(_inner_ty))
3261                                | (WrapperKind::RwLock, Some(_inner_ty)) => {
3262                                    tokens.extend(quote! {
3263                                        #[inline(always)]
3264                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3265                                            rust_key_paths::Kp::new(
3266                                                |root: &#name| match root {
3267                                                    #name::#v_ident(inner) => Some(inner),
3268                                                    _ => None,
3269                                                },
3270                                                |root: &mut #name| match root {
3271                                                    #name::#v_ident(inner) => Some(inner),
3272                                                    _ => None,
3273                                                },
3274                                            )
3275                                        }
3276                                    });
3277                                }
3278                                (WrapperKind::Tagged, Some(inner_ty)) => {
3279                                    tokens.extend(quote! {
3280                                        #[inline(always)]
3281                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3282                                            rust_key_paths::Kp::new(
3283                                                |root: &#name| match root {
3284                                                    #name::#v_ident(inner) => Some(std::ops::Deref::deref(inner)),
3285                                                    _ => None,
3286                                                },
3287                                                |root: &mut #name| match root {
3288                                                    #name::#v_ident(inner) => Some(std::ops::DerefMut::deref_mut(inner)),
3289                                                    _ => None,
3290                                                },
3291                                            )
3292                                        }
3293                                    });
3294                                }
3295                                (WrapperKind::Atomic, None | Some(_)) => {
3296                                    tokens.extend(quote! {
3297                                        #[inline(always)]
3298                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3299                                            rust_key_paths::Kp::new(
3300                                                |root: &#name| match root {
3301                                                    #name::#v_ident(inner) => Some(inner),
3302                                                    _ => None,
3303                                                },
3304                                                |root: &mut #name| match root {
3305                                                    #name::#v_ident(inner) => Some(inner),
3306                                                    _ => None,
3307                                                },
3308                                            )
3309                                        }
3310                                    });
3311                                }
3312                                (WrapperKind::OptionAtomic, 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 { #name::#v_ident(inner) => inner.as_ref(), _ => None },
3318                                                |root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None },
3319                                            )
3320                                        }
3321                                    });
3322                                }
3323                                (WrapperKind::Reference, Some(_inner_ty)) => {
3324                                    tokens.extend(quote! {
3325                                        #[inline(always)]
3326                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3327                                            rust_key_paths::Kp::new(
3328                                                |root: &#name| match root {
3329                                                    #name::#v_ident(inner) => Some(inner),
3330                                                    _ => None,
3331                                                },
3332                                                |_root: &mut #name| None,
3333                                            )
3334                                        }
3335                                    });
3336                                }
3337                                (WrapperKind::Weak, Some(_inner_ty)) => {
3338                                    tokens.extend(quote! {
3339                                        #[inline(always)]
3340                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3341                                            rust_key_paths::Kp::new(
3342                                                |root: &#name| match root {
3343                                                    #name::#v_ident(inner) => Some(inner),
3344                                                    _ => None,
3345                                                },
3346                                                |_root: &mut #name| None,
3347                                            )
3348                                        }
3349                                    });
3350                                }
3351                                (WrapperKind::Cow, Some(inner_ty)) => {
3352                                    tokens.extend(quote! {
3353                                        #[inline(always)]
3354                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3355                                            rust_key_paths::Kp::new(
3356                                                |root: &#name| match root {
3357                                                    #name::#v_ident(inner) => Some(inner.as_ref()),
3358                                                    _ => None,
3359                                                },
3360                                                |root: &mut #name| match root {
3361                                                    #name::#v_ident(inner) => Some(inner.to_mut()),
3362                                                    _ => None,
3363                                                },
3364                                            )
3365                                        }
3366                                    });
3367                                }
3368                                (WrapperKind::OptionBox, Some(inner_ty)) => {
3369                                    // Option<Box<T>>: keypath to T via as_deref() / as_deref_mut()
3370                                    tokens.extend(quote! {
3371                                        #[inline(always)]
3372                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3373                                            rust_key_paths::Kp::new(
3374                                                |root: &#name| match root {
3375                                                    #name::#v_ident(inner) => inner.as_deref(),
3376                                                    _ => None,
3377                                                },
3378                                                |root: &mut #name| match root {
3379                                                    #name::#v_ident(inner) => inner.as_deref_mut(),
3380                                                    _ => None,
3381                                                },
3382                                            )
3383                                        }
3384                                    });
3385                                }
3386                                (WrapperKind::BoxOption, Some(inner_ty)) => {
3387                                    // Box<Option<T>>: keypath to T; inner is &Box<Option<T>>, deref then Option::as_ref/as_mut
3388                                    tokens.extend(quote! {
3389                                        #[inline(always)]
3390                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3391                                            rust_key_paths::Kp::new(
3392                                                |root: &#name| match root {
3393                                                    #name::#v_ident(inner) => (&*inner).as_ref(),
3394                                                    _ => None,
3395                                                },
3396                                                |root: &mut #name| match root {
3397                                                    #name::#v_ident(inner) => (&mut *inner).as_mut(),
3398                                                    _ => None,
3399                                                },
3400                                            )
3401                                        }
3402                                    });
3403                                }
3404                                (WrapperKind::RcOption, Some(inner_ty)) => {
3405                                    // Rc<Option<T>>: keypath to T; get = (&*inner).as_ref(), set = Rc::get_mut then as_mut
3406                                    tokens.extend(quote! {
3407                                        #[inline(always)]
3408                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3409                                            rust_key_paths::Kp::new(
3410                                                |root: &#name| match root {
3411                                                    #name::#v_ident(inner) => (&*inner).as_ref(),
3412                                                    _ => None,
3413                                                },
3414                                                |root: &mut #name| match root {
3415                                                    #name::#v_ident(inner) => std::rc::Rc::get_mut(inner).and_then(std::option::Option::as_mut),
3416                                                    _ => None,
3417                                                },
3418                                            )
3419                                        }
3420                                    });
3421                                }
3422                                (WrapperKind::ArcOption, Some(inner_ty)) => {
3423                                    // Arc<Option<T>>: keypath to T; get = (&*inner).as_ref(), set = Arc::get_mut then as_mut
3424                                    tokens.extend(quote! {
3425                                        #[inline(always)]
3426                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3427                                            rust_key_paths::Kp::new(
3428                                                |root: &#name| match root {
3429                                                    #name::#v_ident(inner) => (&*inner).as_ref(),
3430                                                    _ => None,
3431                                                },
3432                                                |root: &mut #name| match root {
3433                                                    #name::#v_ident(inner) => std::sync::Arc::get_mut(inner).and_then(std::option::Option::as_mut),
3434                                                    _ => None,
3435                                                },
3436                                            )
3437                                        }
3438                                    });
3439                                }
3440                                (WrapperKind::OptionRc, Some(inner_ty)) => {
3441                                    tokens.extend(quote! {
3442                                        #[inline(always)]
3443                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3444                                            rust_key_paths::Kp::new(
3445                                                |root: &#name| match root {
3446                                                    #name::#v_ident(inner) => inner.as_deref(),
3447                                                    _ => None,
3448                                                },
3449                                                |root: &mut #name| match root {
3450                                                    #name::#v_ident(inner) => inner.as_mut().and_then(std::rc::Rc::get_mut),
3451                                                    _ => None,
3452                                                },
3453                                            )
3454                                        }
3455                                    });
3456                                }
3457                                (WrapperKind::OptionArc, Some(inner_ty)) => {
3458                                    tokens.extend(quote! {
3459                                        #[inline(always)]
3460                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3461                                            rust_key_paths::Kp::new(
3462                                                |root: &#name| match root {
3463                                                    #name::#v_ident(inner) => inner.as_deref(),
3464                                                    _ => None,
3465                                                },
3466                                                |root: &mut #name| match root {
3467                                                    #name::#v_ident(inner) => inner.as_mut().and_then(std::sync::Arc::get_mut),
3468                                                    _ => None,
3469                                                },
3470                                            )
3471                                        }
3472                                    });
3473                                }
3474                                (WrapperKind::OptionCow, Some(inner_ty)) => {
3475                                    tokens.extend(quote! {
3476                                        #[inline(always)]
3477                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3478                                            rust_key_paths::Kp::new(
3479                                                |root: &#name| match root {
3480                                                    #name::#v_ident(inner) => inner.as_ref().map(|c| c.as_ref()),
3481                                                    _ => None,
3482                                                },
3483                                                |root: &mut #name| match root {
3484                                                    #name::#v_ident(inner) => inner.as_mut().map(|c| c.to_mut()),
3485                                                    _ => None,
3486                                                },
3487                                            )
3488                                        }
3489                                    });
3490                                }
3491                                (WrapperKind::OptionTagged, Some(inner_ty)) => {
3492                                    tokens.extend(quote! {
3493                                        #[inline(always)]
3494                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3495                                            rust_key_paths::Kp::new(
3496                                                |root: &#name| match root {
3497                                                    #name::#v_ident(inner) => inner.as_ref().map(|t| std::ops::Deref::deref(t)),
3498                                                    _ => None,
3499                                                },
3500                                                |root: &mut #name| match root {
3501                                                    #name::#v_ident(inner) => inner.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
3502                                                    _ => None,
3503                                                },
3504                                            )
3505                                        }
3506                                    });
3507                                }
3508                                (WrapperKind::OptionReference, Some(inner_ty)) => {
3509                                    tokens.extend(quote! {
3510                                        #[inline(always)]
3511                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3512                                            rust_key_paths::Kp::new(
3513                                                |root: &#name| match root {
3514                                                    #name::#v_ident(inner) => inner.as_ref(),
3515                                                    _ => None,
3516                                                },
3517                                                |_root: &mut #name| None,
3518                                            )
3519                                        }
3520                                    });
3521                                }
3522                                (WrapperKind::String, None) => {
3523                                    tokens.extend(quote! {
3524                                        #[inline(always)]
3525                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3526                                            rust_key_paths::Kp::new(
3527                                                |root: &#name| match root {
3528                                                    #name::#v_ident(inner) => Some(inner),
3529                                                    _ => None,
3530                                                },
3531                                                |root: &mut #name| match root {
3532                                                    #name::#v_ident(inner) => Some(inner),
3533                                                    _ => None,
3534                                                },
3535                                            )
3536                                        }
3537                                    });
3538                                }
3539                                (WrapperKind::OptionString, None) => {
3540                                    tokens.extend(quote! {
3541                                        #[inline(always)]
3542                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, std::string::String> {
3543                                            rust_key_paths::Kp::new(
3544                                                |root: &#name| match root {
3545                                                    #name::#v_ident(inner) => inner.as_ref(),
3546                                                    _ => None,
3547                                                },
3548                                                |root: &mut #name| match root {
3549                                                    #name::#v_ident(inner) => inner.as_mut(),
3550                                                    _ => None,
3551                                                },
3552                                            )
3553                                        }
3554                                    });
3555                                }
3556                                (WrapperKind::OnceCell, Some(inner_ty)) => {
3557                                    tokens.extend(quote! {
3558                                        #[inline(always)]
3559                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3560                                            rust_key_paths::Kp::new(
3561                                                |root: &#name| match root {
3562                                                    #name::#v_ident(inner) => inner.get(),
3563                                                    _ => None,
3564                                                },
3565                                                |_root: &mut #name| None,
3566                                            )
3567                                        }
3568                                    });
3569                                }
3570                                (WrapperKind::Lazy, Some(inner_ty)) => {
3571                                    tokens.extend(quote! {
3572                                        #[inline(always)]
3573                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3574                                            rust_key_paths::Kp::new(
3575                                                |root: &#name| match root {
3576                                                    #name::#v_ident(inner) => Some(inner.get()),
3577                                                    _ => None,
3578                                                },
3579                                                |_root: &mut #name| None,
3580                                            )
3581                                        }
3582                                    });
3583                                }
3584                                (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
3585                                    tokens.extend(quote! {
3586                                        #[inline(always)]
3587                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3588                                            rust_key_paths::Kp::new(
3589                                                |root: &#name| match root {
3590                                                    #name::#v_ident(inner) => inner.as_ref().and_then(|c| c.get()),
3591                                                    _ => None,
3592                                                },
3593                                                |_root: &mut #name| None,
3594                                            )
3595                                        }
3596                                    });
3597                                }
3598                                (WrapperKind::OptionLazy, Some(inner_ty)) => {
3599                                    tokens.extend(quote! {
3600                                        #[inline(always)]
3601                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #inner_ty> {
3602                                            rust_key_paths::Kp::new(
3603                                                |root: &#name| match root {
3604                                                    #name::#v_ident(inner) => inner.as_ref().map(|c| c.get()),
3605                                                    _ => None,
3606                                                },
3607                                                |_root: &mut #name| None,
3608                                            )
3609                                        }
3610                                    });
3611                                }
3612                                (WrapperKind::Cell, Some(_inner_ty)) | (WrapperKind::RefCell, Some(_inner_ty))
3613                                | (WrapperKind::PhantomData, Some(_inner_ty)) | (WrapperKind::Range, Some(_inner_ty))
3614                                | (WrapperKind::OptionCell, Some(_inner_ty))
3615                                | (WrapperKind::OptionPhantomData, Some(_inner_ty)) | (WrapperKind::OptionRange, Some(_inner_ty)) => {
3616                                    tokens.extend(quote! {
3617                                        #[inline(always)]
3618                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3619                                            rust_key_paths::Kp::new(
3620                                                |root: &#name| match root {
3621                                                    #name::#v_ident(inner) => Some(inner),
3622                                                    _ => None,
3623                                                },
3624                                                |root: &mut #name| match root {
3625                                                    #name::#v_ident(inner) => Some(inner),
3626                                                    _ => None,
3627                                                },
3628                                            )
3629                                        }
3630                                    });
3631                                }
3632                                (WrapperKind::OptionRefCell, Some(inner_ty)) => {
3633                                    tokens.extend(quote! {
3634                                        #[inline(always)]
3635                                        pub fn #snake() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
3636                                            rust_key_paths::Kp::new(
3637                                                |root: &#name| match root {
3638                                                    #name::#v_ident(inner) => inner.as_ref().map(|r| r.borrow()),
3639                                                    _ => None,
3640                                                },
3641                                                |root: &mut #name| match root {
3642                                                    #name::#v_ident(inner) => inner.as_ref().map(|r| r.borrow_mut()),
3643                                                    _ => None,
3644                                                },
3645                                            )
3646                                        }
3647                                    });
3648                                }
3649                                (WrapperKind::None, None) => {
3650                                    // Basic type
3651                                    tokens.extend(quote! {
3652                                        #[inline(always)]
3653                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3654                                            rust_key_paths::Kp::new(
3655                                                |root: &#name| match root {
3656                                                    #name::#v_ident(inner) => Some(inner),
3657                                                    _ => None,
3658                                                },
3659                                                |root: &mut #name| match root {
3660                                                    #name::#v_ident(inner) => Some(inner),
3661                                                    _ => None,
3662                                                },
3663                                            )
3664                                        }
3665                                    });
3666                                }
3667                                _ => {
3668                                    // Other wrapper types - return keypath to field
3669                                    tokens.extend(quote! {
3670                                        #[inline(always)]
3671                                        pub fn #snake() -> rust_key_paths::KpType<'static, #name, #field_ty> {
3672                                            rust_key_paths::Kp::new(
3673                                                |root: &#name| match root {
3674                                                    #name::#v_ident(inner) => Some(inner),
3675                                                    _ => None,
3676                                                },
3677                                                |root: &mut #name| match root {
3678                                                    #name::#v_ident(inner) => Some(inner),
3679                                                    _ => None,
3680                                                },
3681                                            )
3682                                        }
3683                                    });
3684                                }
3685                            }
3686                        } else {
3687                            // Multi-field tuple variant - return keypath to variant itself
3688                            tokens.extend(quote! {
3689                                #[inline(always)]
3690                                pub fn #snake() -> rust_key_paths::KpType<'static, #name, #name> {
3691                                    rust_key_paths::Kp::new(
3692                                        |root: &#name| match root {
3693                                            #name::#v_ident(..) => Some(root),
3694                                            _ => None,
3695                                        },
3696                                        |root: &mut #name| match root {
3697                                            #name::#v_ident(..) => Some(root),
3698                                            _ => None,
3699                                        },
3700                                    )
3701                                }
3702                            });
3703                        }
3704                    }
3705                    Fields::Named(_) => {
3706                        // Named field variant - return keypath to variant itself
3707                        tokens.extend(quote! {
3708                            pub fn #snake() -> rust_key_paths::KpType<'static, #name, #name> {
3709                                rust_key_paths::Kp::new(
3710                                    |root: &#name| match root {
3711                                        #name::#v_ident { .. } => Some(root),
3712                                        _ => None,
3713                                    },
3714                                    |root: &mut #name| match root {
3715                                        #name::#v_ident { .. } => Some(root),
3716                                        _ => None,
3717                                    },
3718                                )
3719                            }
3720                        });
3721                    }
3722                }
3723            }
3724
3725            tokens
3726        }
3727        Data::Union(_) => {
3728            return syn::Error::new(input_span, "Kp derive does not support unions")
3729            .to_compile_error()
3730            .into();
3731        }
3732    };
3733
3734    let expanded = quote! {
3735        impl #name {
3736            #methods
3737        }
3738    };
3739
3740    TokenStream::from(expanded)
3741}
3742
3743/// Derive macro that generates `partial_kps() -> Vec<PKp<Self>>` returning all field/variant keypaths.
3744/// **Requires `#[derive(Kp)]`** so the keypath accessor methods exist.
3745///
3746/// For structs: returns keypaths for each field. For enums: returns keypaths for each variant
3747/// (using the same methods Kp generates, e.g. `some_variant()`).
3748///
3749/// # Example
3750/// ```
3751/// use key_paths_derive::{Kp, Pkp};
3752/// use rust_key_paths::PKp;
3753///
3754/// #[derive(Kp, Pkp)]
3755/// struct Person {
3756///     name: String,
3757///     age: i32,
3758/// }
3759///
3760/// let kps = Person::partial_kps();
3761/// assert_eq!(kps.len(), 2);
3762/// ```
3763#[proc_macro_derive(Pkp)]
3764pub fn derive_partial_keypaths(input: TokenStream) -> TokenStream {
3765    let input = parse_macro_input!(input as DeriveInput);
3766    let name = &input.ident;
3767
3768    let kp_calls = match &input.data {
3769        Data::Struct(data_struct) => match &data_struct.fields {
3770            Fields::Named(fields_named) => {
3771                let calls: Vec<_> = fields_named
3772                    .named
3773                    .iter()
3774                    .filter_map(|f| f.ident.as_ref())
3775                    .map(|field_ident| {
3776                        quote! { rust_key_paths::PKp::new(Self::#field_ident()) }
3777                    })
3778                    .collect();
3779                quote! { #(#calls),* }
3780            }
3781            Fields::Unnamed(unnamed) => {
3782                let calls: Vec<_> = (0..unnamed.unnamed.len())
3783                    .map(|idx| {
3784                        let kp_fn = format_ident!("f{}", idx);
3785                        quote! { rust_key_paths::PKp::new(Self::#kp_fn()) }
3786                    })
3787                    .collect();
3788                quote! { #(#calls),* }
3789            }
3790            Fields::Unit => quote! {},
3791        },
3792        Data::Enum(data_enum) => {
3793            let calls: Vec<_> = data_enum
3794                .variants
3795                .iter()
3796                .map(|variant| {
3797                    let v_ident = &variant.ident;
3798                    let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
3799                    quote! { rust_key_paths::PKp::new(Self::#snake()) }
3800                })
3801                .collect();
3802            quote! { #(#calls),* }
3803        }
3804        Data::Union(_) => {
3805            return syn::Error::new(
3806                input.ident.span(),
3807                "Pkp derive does not support unions",
3808            )
3809            .to_compile_error()
3810            .into();
3811        }
3812    };
3813
3814    let expanded = quote! {
3815        impl #name {
3816            /// Returns a vec of all field keypaths as partial keypaths (type-erased).
3817            #[inline(always)]
3818            pub fn partial_kps() -> Vec<rust_key_paths::PKp<#name>> {
3819                vec![#kp_calls]
3820            }
3821        }
3822    };
3823
3824    TokenStream::from(expanded)
3825}
3826
3827/// Derive macro that generates `any_kps() -> Vec<AKp>` returning all field/variant keypaths as any keypaths.
3828/// **Requires `#[derive(Kp)]`** so the keypath accessor methods exist.
3829/// AKp type-erases both Root and Value, enabling heterogeneous collections of keypaths.
3830///
3831/// For structs: returns keypaths for each field. For enums: returns keypaths for each variant
3832/// (using the same methods Kp generates, e.g. `some_variant()`).
3833///
3834/// # Example
3835/// ```
3836/// use key_paths_derive::{Kp, Akp};
3837/// use rust_key_paths::AKp;
3838///
3839/// #[derive(Kp, Akp)]
3840/// struct Person {
3841///     name: String,
3842///     age: i32,
3843/// }
3844///
3845/// let kps = Person::any_kps();
3846/// assert_eq!(kps.len(), 2);
3847/// let person = Person { name: "Alice".into(), age: 30 };
3848/// let name: Option<&String> = kps[0].get(&person as &dyn std::any::Any).and_then(|v| v.downcast_ref());
3849/// assert_eq!(name, Some(&"Alice".to_string()));
3850/// ```
3851#[proc_macro_derive(Akp)]
3852pub fn derive_any_keypaths(input: TokenStream) -> TokenStream {
3853    let input = parse_macro_input!(input as DeriveInput);
3854    let name = &input.ident;
3855
3856    let kp_calls = match &input.data {
3857        Data::Struct(data_struct) => match &data_struct.fields {
3858            Fields::Named(fields_named) => {
3859                let calls: Vec<_> = fields_named
3860                    .named
3861                    .iter()
3862                    .filter_map(|f| f.ident.as_ref())
3863                    .map(|field_ident| {
3864                        quote! { rust_key_paths::AKp::new(Self::#field_ident()) }
3865                    })
3866                    .collect();
3867                quote! { #(#calls),* }
3868            }
3869            Fields::Unnamed(unnamed) => {
3870                let calls: Vec<_> = (0..unnamed.unnamed.len())
3871                    .map(|idx| {
3872                        let kp_fn = format_ident!("f{}", idx);
3873                        quote! { rust_key_paths::AKp::new(Self::#kp_fn()) }
3874                    })
3875                    .collect();
3876                quote! { #(#calls),* }
3877            }
3878            Fields::Unit => quote! {},
3879        },
3880        Data::Enum(data_enum) => {
3881            let calls: Vec<_> = data_enum
3882                .variants
3883                .iter()
3884                .map(|variant| {
3885                    let v_ident = &variant.ident;
3886                    let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
3887                    quote! { rust_key_paths::AKp::new(Self::#snake()) }
3888                })
3889                .collect();
3890            quote! { #(#calls),* }
3891        }
3892        Data::Union(_) => {
3893            return syn::Error::new(
3894                input.ident.span(),
3895                "Akp derive does not support unions",
3896            )
3897            .to_compile_error()
3898            .into();
3899        }
3900    };
3901
3902    let expanded = quote! {
3903        impl #name {
3904            /// Returns a vec of all field keypaths as any keypaths (fully type-erased).
3905            #[inline(always)]
3906            pub fn any_kps() -> Vec<rust_key_paths::AKp> {
3907                vec![#kp_calls]
3908            }
3909        }
3910    };
3911
3912    TokenStream::from(expanded)
3913}