Skip to main content

facet_core/impls/std/
locks.rs

1//! Facet implementations for std::sync::{Mutex, RwLock, OnceLock, LazyLock} and their guard types.
2
3use alloc::boxed::Box;
4use core::ptr::NonNull;
5use std::sync::{LazyLock, Mutex, MutexGuard, OnceLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
6
7use crate::{
8    DeclId, Def, Facet, KnownPointer, LockGuardVTable, OxPtrMut, PointerDef, PointerFlags,
9    PointerVTable, PtrConst, PtrMut, PtrUninit, ReadLockResult, Shape, ShapeBuilder, Type,
10    TypeNameOpts, TypeOpsIndirect, TypeParam, UserType, VTableIndirect, Variance, VarianceDep,
11    VarianceDesc, WriteLockResult, decl_id_hash,
12};
13
14// ============================================================================
15// Mutex<T> Implementation
16// ============================================================================
17
18fn type_name_mutex<'a, T: Facet<'a>>(
19    _shape: &'static Shape,
20    f: &mut core::fmt::Formatter<'_>,
21    opts: TypeNameOpts,
22) -> core::fmt::Result {
23    write!(f, "Mutex")?;
24    if let Some(opts) = opts.for_children() {
25        write!(f, "<")?;
26        T::SHAPE.write_type_name(f, opts)?;
27        write!(f, ">")?;
28    } else {
29        write!(f, "<\u{2026}>")?;
30    }
31    Ok(())
32}
33
34unsafe fn mutex_new_into<T>(this: PtrUninit, value: PtrMut) -> PtrMut {
35    unsafe {
36        let t = value.read::<T>();
37        this.put(Mutex::<T>::new(t))
38    }
39}
40
41unsafe fn mutex_drop<T>(ox: OxPtrMut) {
42    unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<Mutex<T>>() as *mut Mutex<T>) }
43}
44
45unsafe fn mutex_lock<'a, T: Facet<'a>>(opaque: PtrConst) -> Result<WriteLockResult, ()> {
46    unsafe {
47        let mutex = &*opaque.as_ptr::<Mutex<T>>();
48
49        // Handle poisoning by ignoring it and proceeding with the inner guard
50        let mut guard = match mutex.lock() {
51            Ok(g) => g,
52            Err(e) => e.into_inner(),
53        };
54
55        // Get pointer to the data through the guard (exclusive access)
56        // Use &mut to get a valid mutable pointer
57        let data_ptr = &mut *guard as *mut T;
58
59        // Box the guard to keep it alive (type-erased)
60        let guard_box = Box::new(guard);
61        let guard_ptr = Box::into_raw(guard_box) as *const u8;
62
63        Ok(WriteLockResult::new(
64            PtrMut::new(data_ptr as *mut u8),
65            PtrConst::new(guard_ptr),
66            &const { mutex_guard_vtable::<T>() },
67        ))
68    }
69}
70
71const fn mutex_guard_vtable<T>() -> LockGuardVTable {
72    unsafe fn drop_guard<T>(guard: PtrConst) {
73        unsafe {
74            drop(Box::from_raw(
75                guard.as_ptr::<MutexGuard<'_, T>>() as *mut MutexGuard<'_, T>
76            ));
77        }
78    }
79
80    LockGuardVTable {
81        drop_in_place: drop_guard::<T>,
82    }
83}
84
85unsafe impl<'a, T: Facet<'a>> Facet<'a> for Mutex<T> {
86    const SHAPE: &'static Shape = &const {
87        ShapeBuilder::for_sized::<Self>("Mutex")
88            .decl_id(DeclId::new(decl_id_hash("#std#Mutex")))
89            .type_name(type_name_mutex::<T>)
90            .vtable_indirect(&VTableIndirect::EMPTY)
91            .type_ops_indirect(
92                &const {
93                    TypeOpsIndirect {
94                        drop_in_place: mutex_drop::<T>,
95                        default_in_place: None,
96                        clone_into: None,
97                        is_truthy: None,
98                    }
99                },
100            )
101            .ty(Type::User(UserType::Opaque))
102            .def(Def::Pointer(PointerDef {
103                vtable: &const {
104                    PointerVTable {
105                        lock_fn: Some(mutex_lock::<T>),
106                        new_into_fn: Some(mutex_new_into::<T>),
107                        ..PointerVTable::new()
108                    }
109                },
110                pointee: Some(T::SHAPE),
111                weak: None,
112                strong: None,
113                flags: PointerFlags::LOCK,
114                known: Some(KnownPointer::Mutex),
115            }))
116            .type_params(&[TypeParam {
117                name: "T",
118                shape: T::SHAPE,
119            }])
120            .inner(T::SHAPE)
121            // Mutex<T> is invariant w.r.t. T because it provides interior mutability
122            .variance(VarianceDesc {
123                base: Variance::Bivariant,
124                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
125            })
126            .build()
127    };
128}
129
130// ============================================================================
131// RwLock<T> Implementation
132// ============================================================================
133
134fn type_name_rwlock<'a, T: Facet<'a>>(
135    _shape: &'static Shape,
136    f: &mut core::fmt::Formatter<'_>,
137    opts: TypeNameOpts,
138) -> core::fmt::Result {
139    write!(f, "RwLock")?;
140    if let Some(opts) = opts.for_children() {
141        write!(f, "<")?;
142        T::SHAPE.write_type_name(f, opts)?;
143        write!(f, ">")?;
144    } else {
145        write!(f, "<\u{2026}>")?;
146    }
147    Ok(())
148}
149
150unsafe fn rwlock_new_into<T>(this: PtrUninit, value: PtrMut) -> PtrMut {
151    unsafe {
152        let t = value.read::<T>();
153        this.put(RwLock::<T>::new(t))
154    }
155}
156
157unsafe fn rwlock_drop<T>(ox: OxPtrMut) {
158    unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<RwLock<T>>() as *mut RwLock<T>) }
159}
160
161const fn rwlock_read_guard_vtable<T>() -> LockGuardVTable {
162    unsafe fn drop_guard<T>(guard: PtrConst) {
163        unsafe {
164            drop(Box::from_raw(
165                guard.as_ptr::<RwLockReadGuard<'_, T>>() as *mut RwLockReadGuard<'_, T>
166            ));
167        }
168    }
169
170    LockGuardVTable {
171        drop_in_place: drop_guard::<T>,
172    }
173}
174
175const fn rwlock_write_guard_vtable<T>() -> LockGuardVTable {
176    unsafe fn drop_guard<T>(guard: PtrConst) {
177        unsafe {
178            drop(Box::from_raw(
179                guard.as_ptr::<RwLockWriteGuard<'_, T>>() as *mut RwLockWriteGuard<'_, T>
180            ));
181        }
182    }
183
184    LockGuardVTable {
185        drop_in_place: drop_guard::<T>,
186    }
187}
188
189unsafe fn rwlock_read<'a, T: Facet<'a>>(opaque: PtrConst) -> Result<ReadLockResult, ()> {
190    unsafe {
191        let rwlock = &*opaque.as_ptr::<RwLock<T>>();
192
193        // Handle poisoning by ignoring it and proceeding with the inner guard
194        let guard = match rwlock.read() {
195            Ok(g) => g,
196            Err(e) => e.into_inner(),
197        };
198
199        // SAFETY: Read lock only provides shared access - use PtrConst
200        let data_ptr = &*guard as *const T;
201        let guard_box = Box::new(guard);
202        let guard_ptr = Box::into_raw(guard_box) as *const u8;
203
204        Ok(ReadLockResult::new(
205            PtrConst::new(data_ptr as *const u8),
206            PtrConst::new(guard_ptr),
207            &const { rwlock_read_guard_vtable::<T>() },
208        ))
209    }
210}
211
212unsafe fn rwlock_write<'a, T: Facet<'a>>(opaque: PtrConst) -> Result<WriteLockResult, ()> {
213    unsafe {
214        let rwlock = &*opaque.as_ptr::<RwLock<T>>();
215
216        // Handle poisoning by ignoring it and proceeding with the inner guard
217        let mut guard = match rwlock.write() {
218            Ok(g) => g,
219            Err(e) => e.into_inner(),
220        };
221
222        // Write lock provides exclusive access - use &mut to get a valid mutable pointer
223        let data_ptr = &mut *guard as *mut T;
224        let guard_box = Box::new(guard);
225        let guard_ptr = Box::into_raw(guard_box) as *const u8;
226
227        Ok(WriteLockResult::new(
228            PtrMut::new(data_ptr as *mut u8),
229            PtrConst::new(guard_ptr),
230            &const { rwlock_write_guard_vtable::<T>() },
231        ))
232    }
233}
234
235unsafe impl<'a, T: Facet<'a>> Facet<'a> for RwLock<T> {
236    const SHAPE: &'static Shape = &const {
237        ShapeBuilder::for_sized::<Self>("RwLock")
238            .decl_id(DeclId::new(decl_id_hash("#std#RwLock")))
239            .type_name(type_name_rwlock::<T>)
240            .vtable_indirect(&VTableIndirect::EMPTY)
241            .type_ops_indirect(
242                &const {
243                    TypeOpsIndirect {
244                        drop_in_place: rwlock_drop::<T>,
245                        default_in_place: None,
246                        clone_into: None,
247                        is_truthy: None,
248                    }
249                },
250            )
251            .ty(Type::User(UserType::Opaque))
252            .def(Def::Pointer(PointerDef {
253                vtable: &const {
254                    PointerVTable {
255                        read_fn: Some(rwlock_read::<T>),
256                        write_fn: Some(rwlock_write::<T>),
257                        new_into_fn: Some(rwlock_new_into::<T>),
258                        ..PointerVTable::new()
259                    }
260                },
261                pointee: Some(T::SHAPE),
262                weak: None,
263                strong: None,
264                flags: PointerFlags::LOCK,
265                known: Some(KnownPointer::RwLock),
266            }))
267            .type_params(&[TypeParam {
268                name: "T",
269                shape: T::SHAPE,
270            }])
271            .inner(T::SHAPE)
272            // RwLock<T> is invariant w.r.t. T because it provides interior mutability
273            .variance(VarianceDesc {
274                base: Variance::Bivariant,
275                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
276            })
277            .build()
278    };
279}
280
281// ============================================================================
282// Guard implementations
283// ============================================================================
284
285fn type_name_mutex_guard<'a, T: Facet<'a>>(
286    _shape: &'static Shape,
287    f: &mut core::fmt::Formatter<'_>,
288    opts: TypeNameOpts,
289) -> core::fmt::Result {
290    write!(f, "MutexGuard")?;
291    if let Some(opts) = opts.for_children() {
292        write!(f, "<")?;
293        T::SHAPE.write_type_name(f, opts)?;
294        write!(f, ">")?;
295    } else {
296        write!(f, "<\u{2026}>")?;
297    }
298    Ok(())
299}
300
301unsafe fn mutex_guard_drop<T>(ox: OxPtrMut) {
302    unsafe {
303        core::ptr::drop_in_place(ox.ptr().as_ptr::<MutexGuard<'_, T>>() as *mut MutexGuard<'_, T>)
304    }
305}
306
307unsafe fn mutex_guard_borrow<'a, T: Facet<'a>>(opaque: PtrConst) -> PtrConst {
308    unsafe {
309        let guard = &*opaque.as_ptr::<MutexGuard<'_, T>>();
310        PtrConst::new(NonNull::from(&**guard).as_ptr())
311    }
312}
313
314unsafe impl<'a, T: Facet<'a>> Facet<'a> for MutexGuard<'a, T> {
315    const SHAPE: &'static Shape = &const {
316        ShapeBuilder::for_sized::<Self>("MutexGuard")
317            .decl_id(DeclId::new(decl_id_hash("#std#MutexGuard")))
318            .type_name(type_name_mutex_guard::<T>)
319            .vtable_indirect(&VTableIndirect::EMPTY)
320            .type_ops_indirect(
321                &const {
322                    TypeOpsIndirect {
323                        drop_in_place: mutex_guard_drop::<T>,
324                        default_in_place: None,
325                        clone_into: None,
326                        is_truthy: None,
327                    }
328                },
329            )
330            .ty(Type::User(UserType::Opaque))
331            .def(Def::Pointer(PointerDef {
332                vtable: &const {
333                    PointerVTable {
334                        borrow_fn: Some(mutex_guard_borrow::<T>),
335                        ..PointerVTable::new()
336                    }
337                },
338                pointee: Some(T::SHAPE),
339                weak: None,
340                strong: None,
341                flags: PointerFlags::empty(),
342                known: None,
343            }))
344            .type_params(&[TypeParam {
345                name: "T",
346                shape: T::SHAPE,
347            }])
348            .inner(T::SHAPE)
349            // MutexGuard<T> is invariant w.r.t. T because it provides mutable access
350            .variance(VarianceDesc {
351                base: Variance::Bivariant,
352                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
353            })
354            .build()
355    };
356}
357
358fn type_name_rwlock_read_guard<'a, T: Facet<'a>>(
359    _shape: &'static Shape,
360    f: &mut core::fmt::Formatter<'_>,
361    opts: TypeNameOpts,
362) -> core::fmt::Result {
363    write!(f, "RwLockReadGuard")?;
364    if let Some(opts) = opts.for_children() {
365        write!(f, "<")?;
366        T::SHAPE.write_type_name(f, opts)?;
367        write!(f, ">")?;
368    } else {
369        write!(f, "<\u{2026}>")?;
370    }
371    Ok(())
372}
373
374unsafe fn rwlock_read_guard_drop<T>(ox: OxPtrMut) {
375    unsafe {
376        core::ptr::drop_in_place(
377            ox.ptr().as_ptr::<RwLockReadGuard<'_, T>>() as *mut RwLockReadGuard<'_, T>
378        )
379    }
380}
381
382unsafe fn rwlock_read_guard_borrow<'a, T: Facet<'a>>(opaque: PtrConst) -> PtrConst {
383    unsafe {
384        let guard = &*opaque.as_ptr::<RwLockReadGuard<'_, T>>();
385        PtrConst::new(NonNull::from(&**guard).as_ptr())
386    }
387}
388
389unsafe impl<'a, T: Facet<'a>> Facet<'a> for RwLockReadGuard<'a, T> {
390    const SHAPE: &'static Shape = &const {
391        ShapeBuilder::for_sized::<Self>("RwLockReadGuard")
392            .decl_id(DeclId::new(decl_id_hash("#std#RwLockReadGuard")))
393            .type_name(type_name_rwlock_read_guard::<T>)
394            .vtable_indirect(&VTableIndirect::EMPTY)
395            .type_ops_indirect(
396                &const {
397                    TypeOpsIndirect {
398                        drop_in_place: rwlock_read_guard_drop::<T>,
399                        default_in_place: None,
400                        clone_into: None,
401                        is_truthy: None,
402                    }
403                },
404            )
405            .ty(Type::User(UserType::Opaque))
406            .def(Def::Pointer(PointerDef {
407                vtable: &const {
408                    PointerVTable {
409                        borrow_fn: Some(rwlock_read_guard_borrow::<T>),
410                        ..PointerVTable::new()
411                    }
412                },
413                pointee: Some(T::SHAPE),
414                weak: None,
415                strong: None,
416                flags: PointerFlags::empty(),
417                known: None,
418            }))
419            .type_params(&[TypeParam {
420                name: "T",
421                shape: T::SHAPE,
422            }])
423            .inner(T::SHAPE)
424            // RwLockReadGuard<T> could be covariant but we keep it bivariant for consistency
425            .variance(VarianceDesc {
426                base: Variance::Bivariant,
427                deps: &const { [VarianceDep::covariant(T::SHAPE)] },
428            })
429            .build()
430    };
431}
432
433fn type_name_rwlock_write_guard<'a, T: Facet<'a>>(
434    _shape: &'static Shape,
435    f: &mut core::fmt::Formatter<'_>,
436    opts: TypeNameOpts,
437) -> core::fmt::Result {
438    write!(f, "RwLockWriteGuard")?;
439    if let Some(opts) = opts.for_children() {
440        write!(f, "<")?;
441        T::SHAPE.write_type_name(f, opts)?;
442        write!(f, ">")?;
443    } else {
444        write!(f, "<\u{2026}>")?;
445    }
446    Ok(())
447}
448
449unsafe fn rwlock_write_guard_drop<T>(ox: OxPtrMut) {
450    unsafe {
451        core::ptr::drop_in_place(
452            ox.ptr().as_ptr::<RwLockWriteGuard<'_, T>>() as *mut RwLockWriteGuard<'_, T>
453        )
454    }
455}
456
457unsafe fn rwlock_write_guard_borrow<'a, T: Facet<'a>>(opaque: PtrConst) -> PtrConst {
458    unsafe {
459        let guard = &*opaque.as_ptr::<RwLockWriteGuard<'_, T>>();
460        PtrConst::new(NonNull::from(&**guard).as_ptr())
461    }
462}
463
464unsafe impl<'a, T: Facet<'a>> Facet<'a> for RwLockWriteGuard<'a, T> {
465    const SHAPE: &'static Shape = &const {
466        ShapeBuilder::for_sized::<Self>("RwLockWriteGuard")
467            .decl_id(DeclId::new(decl_id_hash("#std#RwLockWriteGuard")))
468            .type_name(type_name_rwlock_write_guard::<T>)
469            .vtable_indirect(&VTableIndirect::EMPTY)
470            .type_ops_indirect(
471                &const {
472                    TypeOpsIndirect {
473                        drop_in_place: rwlock_write_guard_drop::<T>,
474                        default_in_place: None,
475                        clone_into: None,
476                        is_truthy: None,
477                    }
478                },
479            )
480            .ty(Type::User(UserType::Opaque))
481            .def(Def::Pointer(PointerDef {
482                vtable: &const {
483                    PointerVTable {
484                        borrow_fn: Some(rwlock_write_guard_borrow::<T>),
485                        ..PointerVTable::new()
486                    }
487                },
488                pointee: Some(T::SHAPE),
489                weak: None,
490                strong: None,
491                flags: PointerFlags::empty(),
492                known: None,
493            }))
494            .type_params(&[TypeParam {
495                name: "T",
496                shape: T::SHAPE,
497            }])
498            .inner(T::SHAPE)
499            // RwLockWriteGuard<T> is invariant w.r.t. T because it provides mutable access
500            .variance(VarianceDesc {
501                base: Variance::Bivariant,
502                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
503            })
504            .build()
505    };
506}
507
508// ============================================================================
509// OnceLock<T> Implementation
510// ============================================================================
511
512fn type_name_oncelock<'a, T: Facet<'a>>(
513    _shape: &'static Shape,
514    f: &mut core::fmt::Formatter<'_>,
515    opts: TypeNameOpts,
516) -> core::fmt::Result {
517    write!(f, "OnceLock")?;
518    if let Some(opts) = opts.for_children() {
519        write!(f, "<")?;
520        T::SHAPE.write_type_name(f, opts)?;
521        write!(f, ">")?;
522    } else {
523        write!(f, "<\u{2026}>")?;
524    }
525    Ok(())
526}
527
528unsafe fn oncelock_new_into<T>(this: PtrUninit, value: PtrMut) -> PtrMut {
529    unsafe {
530        let t = value.read::<T>();
531        let lock = OnceLock::new();
532        lock.set(t).ok();
533        this.put(lock)
534    }
535}
536
537unsafe fn oncelock_drop<T>(ox: OxPtrMut) {
538    unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<OnceLock<T>>() as *mut OnceLock<T>) }
539}
540
541const fn oncelock_guard_vtable() -> LockGuardVTable {
542    const unsafe fn drop_guard(_guard: PtrConst) {
543        // No-op - OnceLock doesn't have a guard to release
544    }
545    LockGuardVTable {
546        drop_in_place: drop_guard,
547    }
548}
549
550/// Read access to OnceLock - returns Err if not yet initialized
551unsafe fn oncelock_read<'a, T: Facet<'a>>(opaque: PtrConst) -> Result<ReadLockResult, ()> {
552    unsafe {
553        let lock = opaque.get::<OnceLock<T>>();
554        match lock.get() {
555            Some(data) => {
556                let data_ptr = NonNull::from(data).as_ptr();
557                // Guard is a null pointer since OnceLock has no actual guard, this is ok since drop is a no-op
558                Ok(ReadLockResult::new(
559                    PtrConst::new(data_ptr as *const u8),
560                    PtrConst::new(core::ptr::null::<()>()),
561                    &const { oncelock_guard_vtable() },
562                ))
563            }
564            None => Err(()),
565        }
566    }
567}
568
569unsafe impl<'a, T: Facet<'a>> Facet<'a> for OnceLock<T> {
570    const SHAPE: &'static Shape = &const {
571        ShapeBuilder::for_sized::<Self>("OnceLock")
572            .decl_id(DeclId::new(decl_id_hash("#std#OnceLock")))
573            .type_name(type_name_oncelock::<T>)
574            .vtable_indirect(&VTableIndirect::EMPTY)
575            .type_ops_indirect(
576                &const {
577                    TypeOpsIndirect {
578                        drop_in_place: oncelock_drop::<T>,
579                        default_in_place: None,
580                        clone_into: None,
581                        is_truthy: None,
582                    }
583                },
584            )
585            .ty(Type::User(UserType::Opaque))
586            .def(Def::Pointer(PointerDef {
587                vtable: &const {
588                    PointerVTable {
589                        read_fn: Some(oncelock_read::<T>),
590                        new_into_fn: Some(oncelock_new_into::<T>),
591                        ..PointerVTable::new()
592                    }
593                },
594                pointee: Some(T::SHAPE),
595                weak: None,
596                strong: None,
597                flags: PointerFlags::empty(),
598                known: Some(KnownPointer::OnceLock),
599            }))
600            .type_params(&[TypeParam {
601                name: "T",
602                shape: T::SHAPE,
603            }])
604            .inner(T::SHAPE)
605            // OnceLock<T> is invariant w.r.t. T because it provides interior mutability
606            .variance(VarianceDesc {
607                base: Variance::Bivariant,
608                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
609            })
610            .build()
611    };
612}
613
614// ============================================================================
615// LazyLock<T, F> Implementation
616// ============================================================================
617
618fn type_name_lazylock<'a, T: Facet<'a>>(
619    _shape: &'static Shape,
620    f: &mut core::fmt::Formatter<'_>,
621    opts: TypeNameOpts,
622) -> core::fmt::Result {
623    write!(f, "LazyLock")?;
624    if let Some(opts) = opts.for_children() {
625        write!(f, "<")?;
626        T::SHAPE.write_type_name(f, opts)?;
627        write!(f, ">")?;
628    } else {
629        write!(f, "<\u{2026}>")?;
630    }
631    Ok(())
632}
633
634unsafe fn lazylock_drop<T, F>(ox: OxPtrMut) {
635    unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<LazyLock<T, F>>() as *mut LazyLock<T, F>) }
636}
637
638/// Borrow access to LazyLock - always succeeds (forces initialization)
639unsafe fn lazylock_borrow<'a, T: Facet<'a>, F: FnOnce() -> T>(opaque: PtrConst) -> PtrConst {
640    unsafe {
641        let lock = opaque.get::<LazyLock<T, F>>();
642        let data = LazyLock::force(lock);
643        PtrConst::new(NonNull::from(data).as_ptr())
644    }
645}
646
647unsafe impl<'a, T: Facet<'a>, F: FnOnce() -> T + 'a> Facet<'a> for LazyLock<T, F> {
648    const SHAPE: &'static Shape = &const {
649        ShapeBuilder::for_sized::<Self>("LazyLock")
650            .decl_id(DeclId::new(decl_id_hash("#std#LazyLock")))
651            .type_name(type_name_lazylock::<T>)
652            .vtable_indirect(&VTableIndirect::EMPTY)
653            .type_ops_indirect(
654                &const {
655                    TypeOpsIndirect {
656                        drop_in_place: lazylock_drop::<T, F>,
657                        default_in_place: None,
658                        clone_into: None,
659                        is_truthy: None,
660                    }
661                },
662            )
663            .ty(Type::User(UserType::Opaque))
664            .def(Def::Pointer(PointerDef {
665                vtable: &const {
666                    PointerVTable {
667                        borrow_fn: Some(lazylock_borrow::<T, F>),
668                        ..PointerVTable::new()
669                    }
670                },
671                pointee: Some(T::SHAPE),
672                weak: None,
673                strong: None,
674                flags: PointerFlags::empty(),
675                known: Some(KnownPointer::LazyLock),
676            }))
677            .type_params(&[TypeParam {
678                name: "T",
679                shape: T::SHAPE,
680            }])
681            .inner(T::SHAPE)
682            // LazyLock<T, F> is invariant w.r.t. T because it provides interior mutability
683            .variance(VarianceDesc {
684                base: Variance::Bivariant,
685                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
686            })
687            .build()
688    };
689}
690
691// ============================================================================
692// Tests
693// ============================================================================
694
695#[cfg(test)]
696mod tests {
697    use super::*;
698    use alloc::string::String;
699
700    // ========================================================================
701    // Shape verification tests
702    // ========================================================================
703
704    #[test]
705    fn test_mutex_shape() {
706        facet_testhelpers::setup();
707
708        let shape = <Mutex<i32>>::SHAPE;
709        assert_eq!(shape.type_identifier, "Mutex");
710
711        // Verify type params
712        let [type_param] = shape.type_params else {
713            panic!("Mutex should have 1 type param");
714        };
715        assert_eq!(type_param.name, "T");
716        assert_eq!(type_param.shape, i32::SHAPE);
717    }
718
719    #[test]
720    fn test_rwlock_shape() {
721        facet_testhelpers::setup();
722
723        let shape = <RwLock<String>>::SHAPE;
724        assert_eq!(shape.type_identifier, "RwLock");
725
726        // Verify type params
727        let [type_param] = shape.type_params else {
728            panic!("RwLock should have 1 type param");
729        };
730        assert_eq!(type_param.name, "T");
731        assert_eq!(type_param.shape, String::SHAPE);
732    }
733
734    #[test]
735    fn test_mutex_guard_shape() {
736        facet_testhelpers::setup();
737
738        let shape = <MutexGuard<'_, i32>>::SHAPE;
739        assert_eq!(shape.type_identifier, "MutexGuard");
740
741        let [type_param] = shape.type_params else {
742            panic!("MutexGuard should have 1 type param");
743        };
744        assert_eq!(type_param.name, "T");
745    }
746
747    #[test]
748    fn test_rwlock_read_guard_shape() {
749        facet_testhelpers::setup();
750
751        let shape = <RwLockReadGuard<'_, i32>>::SHAPE;
752        assert_eq!(shape.type_identifier, "RwLockReadGuard");
753
754        let [type_param] = shape.type_params else {
755            panic!("RwLockReadGuard should have 1 type param");
756        };
757        assert_eq!(type_param.name, "T");
758    }
759
760    #[test]
761    fn test_rwlock_write_guard_shape() {
762        facet_testhelpers::setup();
763
764        let shape = <RwLockWriteGuard<'_, i32>>::SHAPE;
765        assert_eq!(shape.type_identifier, "RwLockWriteGuard");
766
767        let [type_param] = shape.type_params else {
768            panic!("RwLockWriteGuard should have 1 type param");
769        };
770        assert_eq!(type_param.name, "T");
771    }
772
773    // ========================================================================
774    // VTable presence tests
775    // ========================================================================
776
777    #[test]
778    fn test_mutex_vtable() {
779        facet_testhelpers::setup();
780
781        let shape = <Mutex<i32>>::SHAPE;
782        let pointer_def = shape
783            .def
784            .into_pointer()
785            .expect("Mutex should be a pointer type");
786
787        // Mutex should have lock_fn and new_into_fn
788        assert!(
789            pointer_def.vtable.lock_fn.is_some(),
790            "Mutex should have lock_fn"
791        );
792        assert!(
793            pointer_def.vtable.new_into_fn.is_some(),
794            "Mutex should have new_into_fn"
795        );
796
797        // Mutex should NOT have read_fn or write_fn
798        assert!(
799            pointer_def.vtable.read_fn.is_none(),
800            "Mutex should not have read_fn"
801        );
802        assert!(
803            pointer_def.vtable.write_fn.is_none(),
804            "Mutex should not have write_fn"
805        );
806
807        // Verify flags
808        assert!(
809            pointer_def.flags.contains(PointerFlags::LOCK),
810            "Mutex should have LOCK flag"
811        );
812        assert_eq!(pointer_def.known, Some(KnownPointer::Mutex));
813    }
814
815    #[test]
816    fn test_rwlock_vtable() {
817        facet_testhelpers::setup();
818
819        let shape = <RwLock<i32>>::SHAPE;
820        let pointer_def = shape
821            .def
822            .into_pointer()
823            .expect("RwLock should be a pointer type");
824
825        // RwLock should have read_fn, write_fn, and new_into_fn
826        assert!(
827            pointer_def.vtable.read_fn.is_some(),
828            "RwLock should have read_fn"
829        );
830        assert!(
831            pointer_def.vtable.write_fn.is_some(),
832            "RwLock should have write_fn"
833        );
834        assert!(
835            pointer_def.vtable.new_into_fn.is_some(),
836            "RwLock should have new_into_fn"
837        );
838
839        // RwLock should NOT have lock_fn
840        assert!(
841            pointer_def.vtable.lock_fn.is_none(),
842            "RwLock should not have lock_fn"
843        );
844
845        // Verify flags
846        assert!(
847            pointer_def.flags.contains(PointerFlags::LOCK),
848            "RwLock should have LOCK flag"
849        );
850        assert_eq!(pointer_def.known, Some(KnownPointer::RwLock));
851    }
852
853    #[test]
854    fn test_guard_vtables_have_borrow_fn() {
855        facet_testhelpers::setup();
856
857        // MutexGuard
858        let mutex_guard_shape = <MutexGuard<'_, i32>>::SHAPE;
859        let mutex_guard_def = mutex_guard_shape
860            .def
861            .into_pointer()
862            .expect("MutexGuard should be a pointer type");
863        assert!(
864            mutex_guard_def.vtable.borrow_fn.is_some(),
865            "MutexGuard should have borrow_fn"
866        );
867
868        // RwLockReadGuard
869        let read_guard_shape = <RwLockReadGuard<'_, i32>>::SHAPE;
870        let read_guard_def = read_guard_shape
871            .def
872            .into_pointer()
873            .expect("RwLockReadGuard should be a pointer type");
874        assert!(
875            read_guard_def.vtable.borrow_fn.is_some(),
876            "RwLockReadGuard should have borrow_fn"
877        );
878
879        // RwLockWriteGuard
880        let write_guard_shape = <RwLockWriteGuard<'_, i32>>::SHAPE;
881        let write_guard_def = write_guard_shape
882            .def
883            .into_pointer()
884            .expect("RwLockWriteGuard should be a pointer type");
885        assert!(
886            write_guard_def.vtable.borrow_fn.is_some(),
887            "RwLockWriteGuard should have borrow_fn"
888        );
889    }
890
891    // ========================================================================
892    // Functional tests
893    // ========================================================================
894
895    #[test]
896    fn test_mutex_lock_and_access() {
897        facet_testhelpers::setup();
898
899        let mutex = Mutex::new(42i32);
900
901        // Get the shape and pointer def
902        let shape = <Mutex<i32>>::SHAPE;
903        let pointer_def = shape.def.into_pointer().unwrap();
904        let lock_fn = pointer_def.vtable.lock_fn.unwrap();
905
906        // Lock the mutex using the vtable
907        let mutex_ptr = PtrConst::new(&mutex as *const _ as *const u8);
908        let lock_result = unsafe { lock_fn(mutex_ptr) }.expect("Lock should succeed");
909
910        // Access the data through the lock result
911        let data_ptr = lock_result.data();
912        let value = unsafe { data_ptr.as_const().get::<i32>() };
913        assert_eq!(*value, 42);
914
915        // Lock is released when lock_result is dropped
916        drop(lock_result);
917
918        // Verify we can lock again (proves the lock was released)
919        let lock_result2 = unsafe { lock_fn(mutex_ptr) }.expect("Second lock should succeed");
920        drop(lock_result2);
921    }
922
923    #[test]
924    fn test_rwlock_read_access() {
925        facet_testhelpers::setup();
926
927        let rwlock = RwLock::new(String::from("hello"));
928
929        let shape = <RwLock<String>>::SHAPE;
930        let pointer_def = shape.def.into_pointer().unwrap();
931        let read_fn = pointer_def.vtable.read_fn.unwrap();
932
933        let rwlock_ptr = PtrConst::new(&rwlock as *const _ as *const u8);
934
935        // Acquire read lock
936        let read_result = unsafe { read_fn(rwlock_ptr) }.expect("Read lock should succeed");
937
938        // Access the data - ReadLockResult::data() returns &PtrConst directly
939        let data_ptr = read_result.data();
940        let value = unsafe { data_ptr.get::<String>() };
941        assert_eq!(value.as_str(), "hello");
942
943        drop(read_result);
944    }
945
946    #[test]
947    fn test_rwlock_write_access() {
948        facet_testhelpers::setup();
949
950        let rwlock = RwLock::new(100i32);
951
952        let shape = <RwLock<i32>>::SHAPE;
953        let pointer_def = shape.def.into_pointer().unwrap();
954        let write_fn = pointer_def.vtable.write_fn.unwrap();
955
956        let rwlock_ptr = PtrConst::new(&rwlock as *const _ as *const u8);
957
958        // Acquire write lock
959        let write_result = unsafe { write_fn(rwlock_ptr) }.expect("Write lock should succeed");
960
961        // Modify the data through the lock
962        let data_ptr = write_result.data();
963        unsafe {
964            *data_ptr.as_mut_ptr::<i32>() = 200;
965        }
966
967        drop(write_result);
968
969        // Verify the modification persisted
970        let read_fn = pointer_def.vtable.read_fn.unwrap();
971        let read_result = unsafe { read_fn(rwlock_ptr) }.expect("Read lock should succeed");
972        // ReadLockResult::data() returns &PtrConst directly
973        let value = unsafe { read_result.data().get::<i32>() };
974        assert_eq!(*value, 200);
975    }
976
977    #[test]
978    fn test_poisoned_mutex_still_works() {
979        facet_testhelpers::setup();
980
981        let mutex = Mutex::new(42i32);
982
983        // Poison the mutex by panicking while holding the lock
984        let _ = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
985            let _guard = mutex.lock().unwrap();
986            panic!("Intentional panic to poison the mutex");
987        }));
988
989        // The mutex is now poisoned, but we should still be able to access it via vtable
990        let shape = <Mutex<i32>>::SHAPE;
991        let pointer_def = shape.def.into_pointer().unwrap();
992        let lock_fn = pointer_def.vtable.lock_fn.unwrap();
993
994        let mutex_ptr = PtrConst::new(&mutex as *const _ as *const u8);
995
996        // Lock should still succeed (poisoning is ignored)
997        let lock_result =
998            unsafe { lock_fn(mutex_ptr) }.expect("Lock should succeed even when poisoned");
999
1000        // Data should still be accessible
1001        let data_ptr = lock_result.data();
1002        let value = unsafe { data_ptr.as_const().get::<i32>() };
1003        assert_eq!(*value, 42);
1004    }
1005
1006    #[test]
1007    fn test_poisoned_rwlock_still_works() {
1008        facet_testhelpers::setup();
1009
1010        let rwlock = RwLock::new(String::from("hello"));
1011
1012        // Poison the rwlock by panicking while holding the write lock
1013        let _ = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
1014            let _guard = rwlock.write().unwrap();
1015            panic!("Intentional panic to poison the rwlock");
1016        }));
1017
1018        // The rwlock is now poisoned, but we should still be able to access it via vtable
1019        let shape = <RwLock<String>>::SHAPE;
1020        let pointer_def = shape.def.into_pointer().unwrap();
1021        let read_fn = pointer_def.vtable.read_fn.unwrap();
1022
1023        let rwlock_ptr = PtrConst::new(&rwlock as *const _ as *const u8);
1024
1025        // Read should still succeed (poisoning is ignored)
1026        let read_result =
1027            unsafe { read_fn(rwlock_ptr) }.expect("Read should succeed even when poisoned");
1028
1029        // Data should still be accessible
1030        let data_ptr = read_result.data();
1031        let value = unsafe { data_ptr.get::<String>() };
1032        assert_eq!(value.as_str(), "hello");
1033    }
1034
1035    // ========================================================================
1036    // OnceLock tests
1037    // ========================================================================
1038
1039    #[test]
1040    fn test_oncelock_shape() {
1041        facet_testhelpers::setup();
1042
1043        let shape = <OnceLock<i32>>::SHAPE;
1044        assert_eq!(shape.type_identifier, "OnceLock");
1045
1046        let [type_param] = shape.type_params else {
1047            panic!("OnceLock should have 1 type param");
1048        };
1049        assert_eq!(type_param.name, "T");
1050        assert_eq!(type_param.shape, i32::SHAPE);
1051    }
1052
1053    #[test]
1054    fn test_oncelock_vtable() {
1055        facet_testhelpers::setup();
1056
1057        let shape = <OnceLock<i32>>::SHAPE;
1058        let pointer_def = shape
1059            .def
1060            .into_pointer()
1061            .expect("OnceLock should be a pointer type");
1062
1063        // OnceLock should have read_fn and new_into_fn
1064        assert!(
1065            pointer_def.vtable.read_fn.is_some(),
1066            "OnceLock should have read_fn"
1067        );
1068        assert!(
1069            pointer_def.vtable.new_into_fn.is_some(),
1070            "OnceLock should have new_into_fn"
1071        );
1072
1073        // OnceLock should NOT have borrow_fn (fallible read semantics)
1074        assert!(
1075            pointer_def.vtable.borrow_fn.is_none(),
1076            "OnceLock should not have borrow_fn"
1077        );
1078
1079        assert_eq!(pointer_def.known, Some(KnownPointer::OnceLock));
1080    }
1081
1082    #[test]
1083    fn test_oncelock_read_initialized() {
1084        facet_testhelpers::setup();
1085
1086        let lock = OnceLock::new();
1087        lock.set(42i32).ok();
1088
1089        let shape = <OnceLock<i32>>::SHAPE;
1090        let pointer_def = shape.def.into_pointer().unwrap();
1091        let read_fn = pointer_def.vtable.read_fn.unwrap();
1092
1093        let lock_ptr = PtrConst::new(&lock as *const _ as *const u8);
1094        let read_result =
1095            unsafe { read_fn(lock_ptr) }.expect("Read should succeed when initialized");
1096
1097        let value = unsafe { read_result.data().get::<i32>() };
1098        assert_eq!(*value, 42);
1099    }
1100
1101    #[test]
1102    fn test_oncelock_read_uninitialized() {
1103        facet_testhelpers::setup();
1104
1105        let lock: OnceLock<i32> = OnceLock::new();
1106
1107        let shape = <OnceLock<i32>>::SHAPE;
1108        let pointer_def = shape.def.into_pointer().unwrap();
1109        let read_fn = pointer_def.vtable.read_fn.unwrap();
1110
1111        let lock_ptr = PtrConst::new(&lock as *const _ as *const u8);
1112        let result = unsafe { read_fn(lock_ptr) };
1113
1114        assert!(result.is_err(), "Read should fail when uninitialized");
1115    }
1116
1117    // ========================================================================
1118    // LazyLock tests
1119    // ========================================================================
1120
1121    #[test]
1122    fn test_lazylock_shape() {
1123        facet_testhelpers::setup();
1124
1125        let shape = <LazyLock<i32, fn() -> i32>>::SHAPE;
1126        assert_eq!(shape.type_identifier, "LazyLock");
1127
1128        // Only T is exposed as type param, not F
1129        let [type_param] = shape.type_params else {
1130            panic!("LazyLock should have 1 type param");
1131        };
1132        assert_eq!(type_param.name, "T");
1133        assert_eq!(type_param.shape, i32::SHAPE);
1134    }
1135
1136    #[test]
1137    fn test_lazylock_vtable() {
1138        facet_testhelpers::setup();
1139
1140        let shape = <LazyLock<i32, fn() -> i32>>::SHAPE;
1141        let pointer_def = shape
1142            .def
1143            .into_pointer()
1144            .expect("LazyLock should be a pointer type");
1145
1146        // LazyLock should have borrow_fn (infallible, forces initialization)
1147        assert!(
1148            pointer_def.vtable.borrow_fn.is_some(),
1149            "LazyLock should have borrow_fn"
1150        );
1151
1152        // LazyLock should NOT have read_fn (borrow semantics, not lock semantics)
1153        assert!(
1154            pointer_def.vtable.read_fn.is_none(),
1155            "LazyLock should not have read_fn"
1156        );
1157
1158        assert_eq!(pointer_def.known, Some(KnownPointer::LazyLock));
1159    }
1160
1161    #[test]
1162    fn test_lazylock_borrow() {
1163        facet_testhelpers::setup();
1164
1165        let lock: LazyLock<i32, fn() -> i32> = LazyLock::new(|| 42);
1166
1167        let shape = <LazyLock<i32, fn() -> i32>>::SHAPE;
1168        let pointer_def = shape.def.into_pointer().unwrap();
1169        let borrow_fn = pointer_def.vtable.borrow_fn.unwrap();
1170
1171        let lock_ptr = PtrConst::new(&lock as *const _ as *const u8);
1172        let data_ptr = unsafe { borrow_fn(lock_ptr) };
1173
1174        let value = unsafe { data_ptr.get::<i32>() };
1175        assert_eq!(*value, 42);
1176    }
1177}