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 extern "C" 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 extern "C" 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 extern "C" 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 extern "C" 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 extern "C" 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 extern "C" 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 extern "C" fn lazylock_borrow<'a, T: Facet<'a>, F: FnOnce() -> T>(
640    opaque: PtrConst,
641) -> PtrConst {
642    unsafe {
643        let lock = opaque.get::<LazyLock<T, F>>();
644        let data = LazyLock::force(lock);
645        PtrConst::new(NonNull::from(data).as_ptr())
646    }
647}
648
649unsafe impl<'a, T: Facet<'a>, F: FnOnce() -> T + 'a> Facet<'a> for LazyLock<T, F> {
650    const SHAPE: &'static Shape = &const {
651        ShapeBuilder::for_sized::<Self>("LazyLock")
652            .decl_id(DeclId::new(decl_id_hash("#std#LazyLock")))
653            .type_name(type_name_lazylock::<T>)
654            .vtable_indirect(&VTableIndirect::EMPTY)
655            .type_ops_indirect(
656                &const {
657                    TypeOpsIndirect {
658                        drop_in_place: lazylock_drop::<T, F>,
659                        default_in_place: None,
660                        clone_into: None,
661                        is_truthy: None,
662                    }
663                },
664            )
665            .ty(Type::User(UserType::Opaque))
666            .def(Def::Pointer(PointerDef {
667                vtable: &const {
668                    PointerVTable {
669                        borrow_fn: Some(lazylock_borrow::<T, F>),
670                        ..PointerVTable::new()
671                    }
672                },
673                pointee: Some(T::SHAPE),
674                weak: None,
675                strong: None,
676                flags: PointerFlags::empty(),
677                known: Some(KnownPointer::LazyLock),
678            }))
679            .type_params(&[TypeParam {
680                name: "T",
681                shape: T::SHAPE,
682            }])
683            .inner(T::SHAPE)
684            // LazyLock<T, F> is invariant w.r.t. T because it provides interior mutability
685            .variance(VarianceDesc {
686                base: Variance::Bivariant,
687                deps: &const { [VarianceDep::invariant(T::SHAPE)] },
688            })
689            .build()
690    };
691}
692
693// ============================================================================
694// Tests
695// ============================================================================
696
697#[cfg(test)]
698mod tests {
699    use super::*;
700    use alloc::string::String;
701
702    // ========================================================================
703    // Shape verification tests
704    // ========================================================================
705
706    #[test]
707    fn test_mutex_shape() {
708        facet_testhelpers::setup();
709
710        let shape = <Mutex<i32>>::SHAPE;
711        assert_eq!(shape.type_identifier, "Mutex");
712
713        // Verify type params
714        let [type_param] = shape.type_params else {
715            panic!("Mutex should have 1 type param");
716        };
717        assert_eq!(type_param.name, "T");
718        assert_eq!(type_param.shape, i32::SHAPE);
719    }
720
721    #[test]
722    fn test_rwlock_shape() {
723        facet_testhelpers::setup();
724
725        let shape = <RwLock<String>>::SHAPE;
726        assert_eq!(shape.type_identifier, "RwLock");
727
728        // Verify type params
729        let [type_param] = shape.type_params else {
730            panic!("RwLock should have 1 type param");
731        };
732        assert_eq!(type_param.name, "T");
733        assert_eq!(type_param.shape, String::SHAPE);
734    }
735
736    #[test]
737    fn test_mutex_guard_shape() {
738        facet_testhelpers::setup();
739
740        let shape = <MutexGuard<'_, i32>>::SHAPE;
741        assert_eq!(shape.type_identifier, "MutexGuard");
742
743        let [type_param] = shape.type_params else {
744            panic!("MutexGuard should have 1 type param");
745        };
746        assert_eq!(type_param.name, "T");
747    }
748
749    #[test]
750    fn test_rwlock_read_guard_shape() {
751        facet_testhelpers::setup();
752
753        let shape = <RwLockReadGuard<'_, i32>>::SHAPE;
754        assert_eq!(shape.type_identifier, "RwLockReadGuard");
755
756        let [type_param] = shape.type_params else {
757            panic!("RwLockReadGuard should have 1 type param");
758        };
759        assert_eq!(type_param.name, "T");
760    }
761
762    #[test]
763    fn test_rwlock_write_guard_shape() {
764        facet_testhelpers::setup();
765
766        let shape = <RwLockWriteGuard<'_, i32>>::SHAPE;
767        assert_eq!(shape.type_identifier, "RwLockWriteGuard");
768
769        let [type_param] = shape.type_params else {
770            panic!("RwLockWriteGuard should have 1 type param");
771        };
772        assert_eq!(type_param.name, "T");
773    }
774
775    // ========================================================================
776    // VTable presence tests
777    // ========================================================================
778
779    #[test]
780    fn test_mutex_vtable() {
781        facet_testhelpers::setup();
782
783        let shape = <Mutex<i32>>::SHAPE;
784        let pointer_def = shape
785            .def
786            .into_pointer()
787            .expect("Mutex should be a pointer type");
788
789        // Mutex should have lock_fn and new_into_fn
790        assert!(
791            pointer_def.vtable.lock_fn.is_some(),
792            "Mutex should have lock_fn"
793        );
794        assert!(
795            pointer_def.vtable.new_into_fn.is_some(),
796            "Mutex should have new_into_fn"
797        );
798
799        // Mutex should NOT have read_fn or write_fn
800        assert!(
801            pointer_def.vtable.read_fn.is_none(),
802            "Mutex should not have read_fn"
803        );
804        assert!(
805            pointer_def.vtable.write_fn.is_none(),
806            "Mutex should not have write_fn"
807        );
808
809        // Verify flags
810        assert!(
811            pointer_def.flags.contains(PointerFlags::LOCK),
812            "Mutex should have LOCK flag"
813        );
814        assert_eq!(pointer_def.known, Some(KnownPointer::Mutex));
815    }
816
817    #[test]
818    fn test_rwlock_vtable() {
819        facet_testhelpers::setup();
820
821        let shape = <RwLock<i32>>::SHAPE;
822        let pointer_def = shape
823            .def
824            .into_pointer()
825            .expect("RwLock should be a pointer type");
826
827        // RwLock should have read_fn, write_fn, and new_into_fn
828        assert!(
829            pointer_def.vtable.read_fn.is_some(),
830            "RwLock should have read_fn"
831        );
832        assert!(
833            pointer_def.vtable.write_fn.is_some(),
834            "RwLock should have write_fn"
835        );
836        assert!(
837            pointer_def.vtable.new_into_fn.is_some(),
838            "RwLock should have new_into_fn"
839        );
840
841        // RwLock should NOT have lock_fn
842        assert!(
843            pointer_def.vtable.lock_fn.is_none(),
844            "RwLock should not have lock_fn"
845        );
846
847        // Verify flags
848        assert!(
849            pointer_def.flags.contains(PointerFlags::LOCK),
850            "RwLock should have LOCK flag"
851        );
852        assert_eq!(pointer_def.known, Some(KnownPointer::RwLock));
853    }
854
855    #[test]
856    fn test_guard_vtables_have_borrow_fn() {
857        facet_testhelpers::setup();
858
859        // MutexGuard
860        let mutex_guard_shape = <MutexGuard<'_, i32>>::SHAPE;
861        let mutex_guard_def = mutex_guard_shape
862            .def
863            .into_pointer()
864            .expect("MutexGuard should be a pointer type");
865        assert!(
866            mutex_guard_def.vtable.borrow_fn.is_some(),
867            "MutexGuard should have borrow_fn"
868        );
869
870        // RwLockReadGuard
871        let read_guard_shape = <RwLockReadGuard<'_, i32>>::SHAPE;
872        let read_guard_def = read_guard_shape
873            .def
874            .into_pointer()
875            .expect("RwLockReadGuard should be a pointer type");
876        assert!(
877            read_guard_def.vtable.borrow_fn.is_some(),
878            "RwLockReadGuard should have borrow_fn"
879        );
880
881        // RwLockWriteGuard
882        let write_guard_shape = <RwLockWriteGuard<'_, i32>>::SHAPE;
883        let write_guard_def = write_guard_shape
884            .def
885            .into_pointer()
886            .expect("RwLockWriteGuard should be a pointer type");
887        assert!(
888            write_guard_def.vtable.borrow_fn.is_some(),
889            "RwLockWriteGuard should have borrow_fn"
890        );
891    }
892
893    // ========================================================================
894    // Functional tests
895    // ========================================================================
896
897    #[test]
898    fn test_mutex_lock_and_access() {
899        facet_testhelpers::setup();
900
901        let mutex = Mutex::new(42i32);
902
903        // Get the shape and pointer def
904        let shape = <Mutex<i32>>::SHAPE;
905        let pointer_def = shape.def.into_pointer().unwrap();
906        let lock_fn = pointer_def.vtable.lock_fn.unwrap();
907
908        // Lock the mutex using the vtable
909        let mutex_ptr = PtrConst::new(&mutex as *const _ as *const u8);
910        let lock_result = unsafe { lock_fn(mutex_ptr) }.expect("Lock should succeed");
911
912        // Access the data through the lock result
913        let data_ptr = lock_result.data();
914        let value = unsafe { data_ptr.as_const().get::<i32>() };
915        assert_eq!(*value, 42);
916
917        // Lock is released when lock_result is dropped
918        drop(lock_result);
919
920        // Verify we can lock again (proves the lock was released)
921        let lock_result2 = unsafe { lock_fn(mutex_ptr) }.expect("Second lock should succeed");
922        drop(lock_result2);
923    }
924
925    #[test]
926    fn test_rwlock_read_access() {
927        facet_testhelpers::setup();
928
929        let rwlock = RwLock::new(String::from("hello"));
930
931        let shape = <RwLock<String>>::SHAPE;
932        let pointer_def = shape.def.into_pointer().unwrap();
933        let read_fn = pointer_def.vtable.read_fn.unwrap();
934
935        let rwlock_ptr = PtrConst::new(&rwlock as *const _ as *const u8);
936
937        // Acquire read lock
938        let read_result = unsafe { read_fn(rwlock_ptr) }.expect("Read lock should succeed");
939
940        // Access the data - ReadLockResult::data() returns &PtrConst directly
941        let data_ptr = read_result.data();
942        let value = unsafe { data_ptr.get::<String>() };
943        assert_eq!(value.as_str(), "hello");
944
945        drop(read_result);
946    }
947
948    #[test]
949    fn test_rwlock_write_access() {
950        facet_testhelpers::setup();
951
952        let rwlock = RwLock::new(100i32);
953
954        let shape = <RwLock<i32>>::SHAPE;
955        let pointer_def = shape.def.into_pointer().unwrap();
956        let write_fn = pointer_def.vtable.write_fn.unwrap();
957
958        let rwlock_ptr = PtrConst::new(&rwlock as *const _ as *const u8);
959
960        // Acquire write lock
961        let write_result = unsafe { write_fn(rwlock_ptr) }.expect("Write lock should succeed");
962
963        // Modify the data through the lock
964        let data_ptr = write_result.data();
965        unsafe {
966            *data_ptr.as_mut_ptr::<i32>() = 200;
967        }
968
969        drop(write_result);
970
971        // Verify the modification persisted
972        let read_fn = pointer_def.vtable.read_fn.unwrap();
973        let read_result = unsafe { read_fn(rwlock_ptr) }.expect("Read lock should succeed");
974        // ReadLockResult::data() returns &PtrConst directly
975        let value = unsafe { read_result.data().get::<i32>() };
976        assert_eq!(*value, 200);
977    }
978
979    #[test]
980    fn test_poisoned_mutex_still_works() {
981        facet_testhelpers::setup();
982
983        let mutex = Mutex::new(42i32);
984
985        // Poison the mutex by panicking while holding the lock
986        let _ = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
987            let _guard = mutex.lock().unwrap();
988            panic!("Intentional panic to poison the mutex");
989        }));
990
991        // The mutex is now poisoned, but we should still be able to access it via vtable
992        let shape = <Mutex<i32>>::SHAPE;
993        let pointer_def = shape.def.into_pointer().unwrap();
994        let lock_fn = pointer_def.vtable.lock_fn.unwrap();
995
996        let mutex_ptr = PtrConst::new(&mutex as *const _ as *const u8);
997
998        // Lock should still succeed (poisoning is ignored)
999        let lock_result =
1000            unsafe { lock_fn(mutex_ptr) }.expect("Lock should succeed even when poisoned");
1001
1002        // Data should still be accessible
1003        let data_ptr = lock_result.data();
1004        let value = unsafe { data_ptr.as_const().get::<i32>() };
1005        assert_eq!(*value, 42);
1006    }
1007
1008    #[test]
1009    fn test_poisoned_rwlock_still_works() {
1010        facet_testhelpers::setup();
1011
1012        let rwlock = RwLock::new(String::from("hello"));
1013
1014        // Poison the rwlock by panicking while holding the write lock
1015        let _ = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
1016            let _guard = rwlock.write().unwrap();
1017            panic!("Intentional panic to poison the rwlock");
1018        }));
1019
1020        // The rwlock is now poisoned, but we should still be able to access it via vtable
1021        let shape = <RwLock<String>>::SHAPE;
1022        let pointer_def = shape.def.into_pointer().unwrap();
1023        let read_fn = pointer_def.vtable.read_fn.unwrap();
1024
1025        let rwlock_ptr = PtrConst::new(&rwlock as *const _ as *const u8);
1026
1027        // Read should still succeed (poisoning is ignored)
1028        let read_result =
1029            unsafe { read_fn(rwlock_ptr) }.expect("Read should succeed even when poisoned");
1030
1031        // Data should still be accessible
1032        let data_ptr = read_result.data();
1033        let value = unsafe { data_ptr.get::<String>() };
1034        assert_eq!(value.as_str(), "hello");
1035    }
1036
1037    // ========================================================================
1038    // OnceLock tests
1039    // ========================================================================
1040
1041    #[test]
1042    fn test_oncelock_shape() {
1043        facet_testhelpers::setup();
1044
1045        let shape = <OnceLock<i32>>::SHAPE;
1046        assert_eq!(shape.type_identifier, "OnceLock");
1047
1048        let [type_param] = shape.type_params else {
1049            panic!("OnceLock should have 1 type param");
1050        };
1051        assert_eq!(type_param.name, "T");
1052        assert_eq!(type_param.shape, i32::SHAPE);
1053    }
1054
1055    #[test]
1056    fn test_oncelock_vtable() {
1057        facet_testhelpers::setup();
1058
1059        let shape = <OnceLock<i32>>::SHAPE;
1060        let pointer_def = shape
1061            .def
1062            .into_pointer()
1063            .expect("OnceLock should be a pointer type");
1064
1065        // OnceLock should have read_fn and new_into_fn
1066        assert!(
1067            pointer_def.vtable.read_fn.is_some(),
1068            "OnceLock should have read_fn"
1069        );
1070        assert!(
1071            pointer_def.vtable.new_into_fn.is_some(),
1072            "OnceLock should have new_into_fn"
1073        );
1074
1075        // OnceLock should NOT have borrow_fn (fallible read semantics)
1076        assert!(
1077            pointer_def.vtable.borrow_fn.is_none(),
1078            "OnceLock should not have borrow_fn"
1079        );
1080
1081        assert_eq!(pointer_def.known, Some(KnownPointer::OnceLock));
1082    }
1083
1084    #[test]
1085    fn test_oncelock_read_initialized() {
1086        facet_testhelpers::setup();
1087
1088        let lock = OnceLock::new();
1089        lock.set(42i32).ok();
1090
1091        let shape = <OnceLock<i32>>::SHAPE;
1092        let pointer_def = shape.def.into_pointer().unwrap();
1093        let read_fn = pointer_def.vtable.read_fn.unwrap();
1094
1095        let lock_ptr = PtrConst::new(&lock as *const _ as *const u8);
1096        let read_result =
1097            unsafe { read_fn(lock_ptr) }.expect("Read should succeed when initialized");
1098
1099        let value = unsafe { read_result.data().get::<i32>() };
1100        assert_eq!(*value, 42);
1101    }
1102
1103    #[test]
1104    fn test_oncelock_read_uninitialized() {
1105        facet_testhelpers::setup();
1106
1107        let lock: OnceLock<i32> = OnceLock::new();
1108
1109        let shape = <OnceLock<i32>>::SHAPE;
1110        let pointer_def = shape.def.into_pointer().unwrap();
1111        let read_fn = pointer_def.vtable.read_fn.unwrap();
1112
1113        let lock_ptr = PtrConst::new(&lock as *const _ as *const u8);
1114        let result = unsafe { read_fn(lock_ptr) };
1115
1116        assert!(result.is_err(), "Read should fail when uninitialized");
1117    }
1118
1119    // ========================================================================
1120    // LazyLock tests
1121    // ========================================================================
1122
1123    #[test]
1124    fn test_lazylock_shape() {
1125        facet_testhelpers::setup();
1126
1127        let shape = <LazyLock<i32, fn() -> i32>>::SHAPE;
1128        assert_eq!(shape.type_identifier, "LazyLock");
1129
1130        // Only T is exposed as type param, not F
1131        let [type_param] = shape.type_params else {
1132            panic!("LazyLock should have 1 type param");
1133        };
1134        assert_eq!(type_param.name, "T");
1135        assert_eq!(type_param.shape, i32::SHAPE);
1136    }
1137
1138    #[test]
1139    fn test_lazylock_vtable() {
1140        facet_testhelpers::setup();
1141
1142        let shape = <LazyLock<i32, fn() -> i32>>::SHAPE;
1143        let pointer_def = shape
1144            .def
1145            .into_pointer()
1146            .expect("LazyLock should be a pointer type");
1147
1148        // LazyLock should have borrow_fn (infallible, forces initialization)
1149        assert!(
1150            pointer_def.vtable.borrow_fn.is_some(),
1151            "LazyLock should have borrow_fn"
1152        );
1153
1154        // LazyLock should NOT have read_fn (borrow semantics, not lock semantics)
1155        assert!(
1156            pointer_def.vtable.read_fn.is_none(),
1157            "LazyLock should not have read_fn"
1158        );
1159
1160        assert_eq!(pointer_def.known, Some(KnownPointer::LazyLock));
1161    }
1162
1163    #[test]
1164    fn test_lazylock_borrow() {
1165        facet_testhelpers::setup();
1166
1167        let lock: LazyLock<i32, fn() -> i32> = LazyLock::new(|| 42);
1168
1169        let shape = <LazyLock<i32, fn() -> i32>>::SHAPE;
1170        let pointer_def = shape.def.into_pointer().unwrap();
1171        let borrow_fn = pointer_def.vtable.borrow_fn.unwrap();
1172
1173        let lock_ptr = PtrConst::new(&lock as *const _ as *const u8);
1174        let data_ptr = unsafe { borrow_fn(lock_ptr) };
1175
1176        let value = unsafe { data_ptr.get::<i32>() };
1177        assert_eq!(*value, 42);
1178    }
1179}