rec_cell 0.1.0

Zero-cost borrow-checking of aliased references with cyclic construction
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
use core::{
    cell::UnsafeCell,
    fmt::Debug,
    marker::PhantomData,
    mem::{ManuallyDrop, MaybeUninit},
};

#[cfg(feature = "cyclic_with_mut")]
use replace_with::replace_with_or_abort_and_return;

use crate::{
    CyclicBuildable,
    utils::{Invariant, into_ok},
};

macro_rules! cast_ref {
    ($r:expr) => {{
        match $r {
            r => {
                if false {
                    cast_ref_lifetime_check(r)
                } else {
                    #[allow(clippy::ptr_as_ptr, clippy::ref_as_ptr)]
                    &*(r as *const _ as *const _)
                }
            }
        }
    }};
    (mut $r:expr) => {{
        match $r {
            r => {
                if false {
                    cast_mut_lifetime_check(r)
                } else {
                    #[allow(clippy::ptr_as_ptr, clippy::ref_as_ptr)]
                    &mut *(r as *mut _ as *mut _)
                }
            }
        }
    }};
}

// Sanity checks for cast_ref: Input and output lifetimes must be the same.
const fn cast_ref_lifetime_check<T: ?Sized, U: ?Sized>(_: &T) -> &U {
    unimplemented!()
}
const fn cast_mut_lifetime_check<T: ?Sized, U: ?Sized>(_: &mut T) -> &mut U {
    unimplemented!()
}

/// A token that grants access to [`RecCell`] values from the same scope.
///
/// Tokens are created with [`RecToken::new`], which runs a closure while the
/// token is alive. The token's lifetime ties it to the cells it may unlock.
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct RecToken<'t> {
    _phantom: Invariant<'t>,
}

impl<'t> RecToken<'t> {
    /// Creates a fresh, non-escaping token for a lexical scope.
    ///
    /// The closure receives the token by value and may use it to construct or
    /// access [`RecCell`] values that share the same token lifetime. When the
    /// closure returns, the token is consumed.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|token| {
    ///     let cell = RecCell::new(1);
    ///     assert_eq!(*cell.borrow(&token), 1);
    /// });
    /// ```
    #[allow(clippy::new_ret_no_self, reason = "same conventions as GhostToken")]
    pub fn new<R>(scope: impl FnOnce(RecToken<'_>) -> R) -> R {
        scope(RecToken {
            _phantom: PhantomData,
        })
    }

    /// Initializes one or more cyclic cells and returns the token afterwards.
    ///
    /// `uninit` may be a slot, array, or tuple of slots. The closure receives
    /// references to their future cells and must return values for every slot.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::RecToken;
    ///
    /// RecToken::new(|token| {
    ///     let (mut first, mut second) = (MaybeUninit::uninit(), MaybeUninit::uninit());
    ///     let ((first, second), token) = token.make_cyclic(
    ///         (&mut first, &mut second),
    ///         |(first, second)| ((first, second), (1, 2)),
    ///     );
    ///     assert_eq!((*first.borrow(&token), *second.borrow(&token)), (1, 2));
    /// });
    /// ```
    pub fn make_cyclic<'a, U, R>(
        self,
        uninit: U,
        scope: impl FnOnce(U::ScopeInput<'t>) -> (R, U::ScopeOutput<'t>),
    ) -> (R, Self)
    where
        U: CyclicBuildable<'a>,
        't: 'a,
    {
        into_ok(self.try_make_cyclic(uninit, move |input| Ok(scope(input))))
    }

    /// Initializes one or more cyclic cells using a mutable reference to the
    /// token.
    ///
    /// On panic of the closure `scope`, the process will abort to avoid
    /// returning control while the cells are yet to be initialized.
    ///
    /// # Examples
    ///
    /// ```
    /// # #[cfg(feature = "cyclic_with_mut")]
    /// # {
    /// use core::mem::MaybeUninit;
    /// use rec_cell::RecToken;
    ///
    /// RecToken::new(|mut token| {
    ///     let mut slot = MaybeUninit::uninit();
    ///     let value = token.make_cyclic_with_mut(&mut slot, |_| (7, 11));
    ///     assert_eq!(value, 7);
    ///     assert_eq!(unsafe { slot.assume_init_ref() }, &11);
    /// });
    /// # }
    /// ```
    #[cfg(feature = "cyclic_with_mut")]
    pub fn make_cyclic_with_mut<'a, U, R>(
        &mut self,
        uninit: U,
        scope: impl FnOnce(U::ScopeInput<'t>) -> (R, U::ScopeOutput<'t>),
    ) -> R
    where
        U: CyclicBuildable<'a>,
        't: 'a,
    {
        replace_with_or_abort_and_return(self, move |token| token.make_cyclic(uninit, scope))
    }

    /// Fallible version of [`Self::make_cyclic`].
    ///
    /// On error the token is consumed, preventing access to a possibly
    /// uninitialized cell. No output value is written on that path.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    ///
    /// RecToken::new(|token| {
    ///     let mut slot = MaybeUninit::uninit();
    ///     let (value, token) = token.try_make_cyclic(&mut slot, |_| Ok::<_, ()>((7, 11))).unwrap();
    ///     assert_eq!(value, 7);
    ///     assert_eq!(unsafe { slot.assume_init_ref() }, &11);
    /// });
    /// ```
    ///
    /// A closure may return an error before writing its output:
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::RecToken;
    ///
    /// RecToken::new(|token| {
    ///     let mut slot = MaybeUninit::<usize>::uninit();
    ///     let result = token.try_make_cyclic(&mut slot, |_| Err::<((), usize), _>("failed"));
    ///     assert!(matches!(result, Err("failed")));
    /// });
    /// ```
    ///
    /// The consumed token prevents access to other slots after a failed
    /// initialization, since the failed slot may be uninitialized:
    ///
    /// ```compile_fail
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    ///
    /// RecToken::new(|token| {
    ///     let cell = RecCell::new(42);
    ///     let mut slot = MaybeUninit::<usize>::uninit();
    ///     let _ = token.try_make_cyclic(&mut slot, |_| Err::<((), usize), _>("failed"));
    ///     assert_eq!(*cell.borrow(&token), 42);
    /// });
    /// ```
    pub fn try_make_cyclic<'a, U, R, E>(
        self,
        uninit: U,
        scope: impl FnOnce(U::ScopeInput<'t>) -> Result<(R, U::ScopeOutput<'t>), E>,
    ) -> Result<(R, Self), E>
    where
        U: CyclicBuildable<'a>,
        't: 'a,
    {
        self.with_builder(move |builder| {
            builder.try_add(uninit, move |builder, input| {
                let (result, output) = scope(input)?;
                Ok((result, builder, output))
            })
        })
    }
}

impl Debug for RecToken<'_> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("RecToken").finish_non_exhaustive()
    }
}

/// A cell that can be used to create recursive data structures.
///
/// `RecCell` stores a value that can only be accessed through a matching
/// [`RecToken`]. This makes it useful for self-referential or mutually
/// recursive structures where you want controlled shared or mutable access to
/// otherwise interior-mutable data.
///
/// # Examples
///
/// Construction, shared/mutable borrowing, direct exclusive access, and
/// extraction:
///
/// ```
/// use rec_cell::{RecCell, RecToken};
///
/// RecToken::new(|mut token| {
///     let mut cell = RecCell::new(1);
///     assert_eq!(*cell.borrow(&token), 1);
///     *cell.borrow_mut(&mut token) = 2;
///     *cell.get_mut() = 3;
///     assert_eq!(cell.into_inner(), 3);
/// });
/// ```
///
/// Reinterpreting existing storage, slices, and arrays:
///
/// ```
/// use rec_cell::{RecCell, RecToken};
///
/// RecToken::new(|mut token| {
///     let mut values = [1, 2];
///     let cells = RecCell::from_slice_mut(&mut values);
///     RecCell::borrow_slice_mut(cells, &mut token)[0] = 3;
///     assert_eq!(RecCell::borrow_slice(cells, &token), &[3, 2]);
///
///     let mut array = RecCell::new([4, 5]);
///     let elements = array.as_array_of_cells_mut();
///     *elements[1].get_mut() = 6;
///     assert_eq!(RecCell::from_array_of_cells(elements).borrow(&token), &[4, 6]);
/// });
/// ```
#[repr(transparent)]
pub struct RecCell<'t, T> {
    _phantom: Invariant<'t>,
    data: UnsafeCell<MaybeUninit<T>>,
}

impl<'t, T> RecCell<'t, T> {
    /// Constructs a new instance of `RecCell` which will wrap the specified
    /// value.
    ///
    /// The cell constructed through this method will drop its inner value when
    /// dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let cell = RecCell::new(5);
    /// assert_eq!(cell.into_inner(), 5);
    /// ```
    pub const fn new(value: T) -> Self {
        Self {
            _phantom: PhantomData,
            data: UnsafeCell::new(MaybeUninit::new(value)),
        }
    }

    /// Unwraps the value, consuming the cell.
    ///
    /// No token is required because consuming the cell proves exclusive access.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// assert_eq!(RecCell::new("value").into_inner(), "value");
    /// ```
    pub const fn into_inner(self) -> T {
        let this = ManuallyDrop::new(self);
        // SAFETY: `self` owns an initialized `T`; `ManuallyDrop` prevents a second
        // drop.
        unsafe { (&raw const this).cast::<T>().read() }
    }

    /// Initializes a recursive cell from uninitialized storage.
    ///
    /// This is the infallible form of [`RecCell::try_new_cyclic`]. The closure
    /// is given a reference to the not-yet-initialized cell, which can be
    /// used to construct values that refer back to it. The destructor of the
    /// constructed value will not be run unless explicitly called afterwards.
    ///
    /// If you want to initialize uninitialized storage but do not need the
    /// self-referential capability, consider
    /// `RecCell::from_mut(uninit.write(value))` instead.
    ///
    /// This function takes the token by value, rather than by mutable
    /// reference, so that it would be impossible to access the
    /// uninitialized cell within the scope or if the closure panics.
    #[cfg_attr(
        feature = "cyclic_with_mut",
        doc = "If you want to use `&mut RecToken`, consider [`RecCell::new_cyclic_with_mut`]."
    )]
    ///
    /// If you want to initialize multiple cells at once, consider
    /// [`RecToken::make_cyclic`].
    ///
    /// # Examples
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    ///
    /// struct SelfRef<'a, 't>(&'static str, &'a RecCell<'t, Self>);
    /// RecToken::new(|token| {
    ///     let mut slot = MaybeUninit::uninit();
    ///     let (cell, token) = RecCell::new_cyclic(&mut slot, token, |cell| (cell, SelfRef("value", cell)));
    ///     assert_eq!(cell.borrow(&token).0, "value");
    ///     assert_eq!(cell.borrow(&token).1.borrow(&token).0, "value");
    /// });
    /// ```
    pub fn new_cyclic<'a, R>(
        uninit: &'a mut MaybeUninit<T>,
        token: RecToken<'t>,
        scope: impl FnOnce(&'a Self) -> (R, T),
    ) -> (R, RecToken<'t>)
    where
        't: 'a,
    {
        token.make_cyclic(uninit, scope)
    }

    /// Initializes a recursive cell from uninitialized storage, using a mutable
    /// reference to the token.
    ///
    /// On panic of the closure `scope`, the process will abort to avoid
    /// returning control while the cell is yet to be initialized.
    ///
    /// # Examples
    ///
    /// ```
    /// # #[cfg(feature = "cyclic_with_mut")]
    /// # {
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|mut token| {
    ///     let mut slot = MaybeUninit::uninit();
    ///     let value = RecCell::new_cyclic_with_mut(&mut slot, &mut token, |_| ((), 4));
    ///     assert_eq!(value, ());
    /// });
    /// # }
    /// ```
    #[cfg(feature = "cyclic_with_mut")]
    pub fn new_cyclic_with_mut<'a, R>(
        uninit: &'a mut MaybeUninit<T>,
        token: &mut RecToken<'t>,
        scope: impl FnOnce(&'a Self) -> (R, T),
    ) -> R
    where
        't: 'a,
    {
        replace_with_or_abort_and_return(token, move |token| Self::new_cyclic(uninit, token, scope))
    }

    /// Initializes a recursive cell from uninitialized storage, allowing
    /// failure.
    ///
    /// The closure may return an error before the value is written. The token
    /// is taken by value so it cannot be used to access the cell while the
    /// cell is still uninitialized.
    ///
    /// If a failure occurs, the caller will be locked out of accessing any of
    /// the cells under the same token. This is because the newly created
    /// cell has not been initialized and we cannot distinguish between that
    /// and initialized cells.
    ///
    /// If you want to initialize multiple cells at once, consider
    /// [`RecToken::try_make_cyclic`].
    ///
    /// # Examples
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|token| {
    ///     let mut slot = MaybeUninit::uninit();
    ///     let (value, _) = RecCell::try_new_cyclic(&mut slot, token, |_| Ok::<_, ()>((7, 1))).unwrap();
    ///     assert_eq!(value, 7);
    /// });
    /// ```
    ///
    /// A closure may return an error before writing the cell:
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    ///
    /// RecToken::new(|token| {
    ///     let mut slot = MaybeUninit::<usize>::uninit();
    ///     let result = RecCell::try_new_cyclic(
    ///         &mut slot,
    ///         token,
    ///         |_| Err::<((), usize), _>("failed"),
    ///     );
    ///     assert!(matches!(result, Err("failed")));
    /// });
    /// ```
    ///
    /// Accessing any slot through the token after an error does not compile,
    /// because the slot is yet to be initialized:
    ///
    /// ```compile_fail
    /// use core::mem::MaybeUninit;
    /// use rec_cell::{RecCell, RecToken};
    ///
    /// RecToken::new(|token| {
    ///     let cell = RecCell::new(42);
    ///     let mut slot = MaybeUninit::<usize>::uninit();
    ///     let bad_slot = RecCell::try_new_cyclic(
    ///         &mut slot,
    ///         token,
    ///         |slot| Err::<((), usize), _>(slot),
    ///     ).unwrap_err();
    ///
    ///     // At this point, bad_slot and &cell have the exact same type.
    ///     // We must not access bad_slot, so the following must also fail
    ///     // to compile:
    ///     assert_eq!(*cell.borrow(&token), 42);
    /// });
    /// ```
    pub fn try_new_cyclic<'a, R, E>(
        uninit: &'a mut MaybeUninit<T>,
        // This must be taken by value, since otherwise if `scope` fails, the caller would be able
        // to use the RecToken to access the uninitialized RecCell.
        token: RecToken<'t>,
        scope: impl FnOnce(&'a Self) -> Result<(R, T), E>,
    ) -> Result<(R, RecToken<'t>), E>
    where
        't: 'a,
    {
        token.try_make_cyclic(uninit, scope)
    }

    /// Converts from `&mut T` to `&mut RecCell<T>` without moving the value.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let mut value = 1;
    /// *RecCell::from_mut(&mut value).get_mut() = 2;
    /// assert_eq!(value, 2);
    /// ```
    pub const fn from_mut(value: &mut T) -> &mut Self {
        // SAFETY: `RecCell<T>` is transparent over `T`.
        unsafe { cast_ref!(mut value) }
    }

    /// Converts from `&mut [T]` to `&mut [RecCell<T>]` without moving values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let mut values = [1, 2];
    /// *RecCell::from_slice_mut(&mut values)[0].get_mut() = 3;
    /// assert_eq!(values, [3, 2]);
    /// ```
    pub const fn from_slice_mut(value: &mut [T]) -> &mut [Self] {
        // SAFETY: `RecCell<T>` is transparent over `T` element-wise.
        unsafe { cast_ref!(mut value) }
    }

    /// Returns a mutable reference to the underlying data.
    ///
    /// This call borrows the `RecCell` mutably, which guarantees that
    /// no borrows to the underlying data exist.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let mut cell = RecCell::new(1);
    /// *cell.get_mut() = 2;
    /// assert_eq!(cell.into_inner(), 2);
    /// ```
    pub const fn get_mut(&mut self) -> &mut T {
        // SAFETY: exclusive access permits viewing the transparent representation.
        unsafe { cast_ref!(mut self) }
    }

    /// Returns a mutable reference to the underlying slice.
    ///
    /// This call borrows the slice of `RecCell`s mutably.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let mut cells = [RecCell::new(1), RecCell::new(2)];
    /// RecCell::get_slice_mut(&mut cells)[1] = 3;
    /// assert_eq!(cells[1].get_mut(), &mut 3);
    /// ```
    pub const fn get_slice_mut(this: &mut [Self]) -> &mut [T] {
        // SAFETY: exclusive access permits viewing the transparent representation.
        unsafe { cast_ref!(mut this) }
    }

    /// Returns a raw pointer to the stored value.
    ///
    /// Dereferencing it is unsafe. Do not use it to destroy a cyclically
    /// initialized value while its token remains usable.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// let cell = RecCell::new(1);
    /// assert!(!cell.as_ptr().is_null());
    /// ```
    pub const fn as_ptr(&self) -> *mut T {
        self.data.get().cast()
    }

    /// Returns a raw pointer to the stored slice value.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let cells = [RecCell::new(1), RecCell::new(2)];
    /// assert_eq!(RecCell::as_slice_ptr(&cells).len(), 2);
    /// ```
    pub const fn as_slice_ptr(this: &[Self]) -> *mut [T] {
        let cells = core::ptr::from_ref(this) as *const UnsafeCell<[MaybeUninit<T>]>;
        UnsafeCell::raw_get(cells) as *mut [T]
    }

    /// Borrows the stored value with a matching token.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|token| {
    ///     let cell = RecCell::new(1);
    ///     assert_eq!(*cell.borrow(&token), 1);
    /// });
    /// ```
    pub const fn borrow<'a>(&'a self, _: &'a RecToken<'t>) -> &'a T {
        // SAFETY: a matching token proves this initialized cell may be shared.
        unsafe { &*self.as_ptr() }
    }

    /// Borrows a slice of cells with a matching token.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|token| {
    ///     let cells = [RecCell::new(1), RecCell::new(2)];
    ///     assert_eq!(RecCell::borrow_slice(&cells, &token), &[1, 2]);
    /// });
    /// ```
    pub const fn borrow_slice<'a>(this: &'a [Self], _: &'a RecToken<'t>) -> &'a [T] {
        // SAFETY: a matching token proves these initialized cells may be shared.
        unsafe { &*Self::as_slice_ptr(this) }
    }

    /// Mutably borrows the stored value with a matching token.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|mut token| {
    ///     let cell = RecCell::new(1);
    ///     *cell.borrow_mut(&mut token) = 2;
    ///     assert_eq!(*cell.borrow(&token), 2);
    /// });
    /// ```
    #[allow(clippy::mut_from_ref, reason = "the whole point of this crate")]
    pub const fn borrow_mut<'a>(&'a self, _: &'a mut RecToken<'t>) -> &'a mut T {
        // SAFETY: the exclusive token borrow excludes every other borrow.
        unsafe { &mut *self.as_ptr() }
    }

    /// Mutably borrows a slice of cells with a matching token.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|mut token| {
    ///     let cells = [RecCell::new(1), RecCell::new(2)];
    ///     RecCell::borrow_slice_mut(&cells, &mut token)[0] = 3;
    ///     assert_eq!(RecCell::borrow_slice(&cells, &token), &[3, 2]);
    /// });
    /// ```
    pub const fn borrow_slice_mut<'a>(this: &'a [Self], _: &'a mut RecToken<'t>) -> &'a mut [T] {
        // SAFETY: the exclusive token borrow excludes every other borrow.
        unsafe { &mut *Self::as_slice_ptr(this) }
    }

    // We do not support mutably borrowing multiple cells at once. For an in-depth
    // discussion of the issue and the complexity of a possible implementation,
    // see: https://github.com/matthieu-m/ghost-cell/blob/956df44625bda13793defc4a826431ad9ab7789c/src/ghost_borrow_mut.rs

    /// Creates a reference to an uninitialized `RecCell` from uninitialized
    /// storage.
    ///
    /// This must only be used when the `RecToken` is guaranteed to be taken
    /// out of circulation. You must call
    /// [`write_to_uninit`][Self::write_to_uninit] on the returned
    /// reference before the `RecToken` is made available to safe code again,
    /// by wrapping your code with an API similar to [`RecCell::new_cyclic`].
    ///
    /// # Safety
    ///
    /// The caller must keep the matching token unavailable to safe code until
    /// a value has been written with
    /// [`write_to_uninit`][Self::write_to_uninit].
    ///
    /// # Examples
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::RecCell;
    /// let mut slot = MaybeUninit::uninit();
    /// let cell = unsafe { RecCell::from_uninit(&mut slot) };
    /// unsafe { cell.write_to_uninit(1) };
    /// assert_eq!(unsafe { slot.assume_init() }, 1);
    /// ```
    pub const unsafe fn from_uninit(uninit: &mut MaybeUninit<T>) -> &Self {
        // SAFETY: upheld by this function's safety contract.
        unsafe { cast_ref!(mut uninit) }
    }

    /// Writes a value to a cell produced by [`Self::from_uninit`].
    ///
    /// This should only be paired with [`from_uninit`][Self::from_uninit] to
    /// create a self-referential structure. The `RecToken` must be taken
    /// out of circulation after `from_uninit` is called and before this method
    /// is called.
    ///
    /// # Safety
    ///
    /// `self` must have been created by [`Self::from_uninit`], must not already
    /// contain a value, and the matching token must remain unavailable.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::mem::MaybeUninit;
    /// use rec_cell::RecCell;
    /// let mut slot = MaybeUninit::uninit();
    /// let cell = unsafe { RecCell::from_uninit(&mut slot) };
    /// unsafe { cell.write_to_uninit(3) };
    /// assert_eq!(unsafe { slot.assume_init() }, 3);
    /// ```
    pub const unsafe fn write_to_uninit(&self, value: T) {
        // SAFETY: upheld by this function's safety contract.
        unsafe { self.as_ptr().write(value) }
    }
}

impl<'t, T, const N: usize> RecCell<'t, [T; N]> {
    /// Views an array-valued cell as an array of element cells.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|token| {
    ///     let cell = RecCell::new([1, 2]);
    ///     assert_eq!(*cell.as_array_of_cells()[0].borrow(&token), 1);
    /// });
    /// ```
    pub const fn as_array_of_cells(&self) -> &[RecCell<'t, T>; N] {
        // SAFETY: array-of-cells and cell-of-array have identical layout.
        unsafe { cast_ref!(self) }
    }

    /// Views an array-valued cell as a mutable array of element cells.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let mut cell = RecCell::new([1, 2]);
    /// *cell.as_array_of_cells_mut()[0].get_mut() = 3;
    /// assert_eq!(cell.into_inner(), [3, 2]);
    /// ```
    pub const fn as_array_of_cells_mut(&mut self) -> &mut [RecCell<'t, T>; N] {
        // SAFETY: array-of-cells and cell-of-array have identical layout.
        unsafe { cast_ref!(mut self) }
    }

    /// Reinterprets an array of element cells as a cell containing the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::{RecCell, RecToken};
    /// RecToken::new(|token| {
    ///     let cells = [RecCell::new(1), RecCell::new(2)];
    ///     assert_eq!(RecCell::from_array_of_cells(&cells).borrow(&token), &[1, 2]);
    /// });
    /// ```
    pub const fn from_array_of_cells<'a>(cells: &'a [RecCell<'t, T>; N]) -> &'a Self {
        // SAFETY: array-of-cells and cell-of-array have identical layout.
        unsafe { cast_ref!(cells) }
    }

    /// Reinterprets a mutable array of element cells as a mutable array-valued
    /// cell.
    ///
    /// # Examples
    ///
    /// ```
    /// use rec_cell::RecCell;
    /// let mut cells = [RecCell::new(1), RecCell::new(2)];
    /// RecCell::from_array_of_cells_mut(&mut cells).get_mut()[0] = 3;
    /// assert_eq!(cells[0].get_mut(), &mut 3);
    /// ```
    pub const fn from_array_of_cells_mut<'a>(cells: &'a mut [RecCell<'t, T>; N]) -> &'a mut Self {
        // SAFETY: array-of-cells and cell-of-array have identical layout.
        unsafe { cast_ref!(mut cells) }
    }
}

// The following Send/Sync impls are same as those in GhostCell.

// SAFETY: An owned `RecCell<'_, T>` is conceptually equivalent to a `T`, and
// can be sent across threads if `T` can.
unsafe impl<T: Send> Send for RecCell<'_, T> {}
// SAFETY: A `&RecCell<'_, T>` can be used to access either a `&T` or a
// `&mut T`, and the latter can be used to obtain a `T`. Therefore, a
// `RecCell<'_, T>` is Sync only if `T` is Send and Sync.
unsafe impl<T: Send + Sync> Sync for RecCell<'_, T> {}

impl<T> Drop for RecCell<'_, T> {
    fn drop(&mut self) {
        // SAFETY: owned `RecCell` storage contains one initialized `T`.
        unsafe { self.as_ptr().drop_in_place() }
    }
}

impl<T: AsMut<U>, U: ?Sized> AsMut<U> for RecCell<'_, T> {
    fn as_mut(&mut self) -> &mut U {
        self.get_mut().as_mut()
    }
}

impl<T> From<T> for RecCell<'_, T> {
    fn from(value: T) -> Self {
        Self::new(value)
    }
}

impl<T: Default> Default for RecCell<'_, T> {
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<T> Debug for RecCell<'_, T> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("RecCell").finish_non_exhaustive()
    }
}