unchecked_refcell/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use core::fmt;
4use core::{
5    cell::{Cell, UnsafeCell},
6    cmp::Ordering,
7    fmt::{Debug, Display, Formatter},
8    marker::PhantomData,
9    mem,
10    ops::{Deref, DerefMut},
11    ptr::NonNull,
12};
13
14/// A mutable memory location with dynamically checked borrow rules.
15///
16/// `UncheckedRefCell` behaves exactly like `std::cell::RefCell` when `debug_assertions` is enabled or `checked` feature
17/// flag is enabled (for non-release-like builds). For release-like builds, `UncheckedRefCell` does not
18/// perform any borrow checking. Thus it is faster than `RefCell` (see benchmarks), but may lead to
19/// undefined behavior instead of panicking like `RefCell`. Use this over `RefCell` for performance
20/// critical code where it is known a `RefCell` would never panic.
21pub struct UncheckedRefCell<T: ?Sized> {
22    #[cfg(any(feature = "checked", debug_assertions))]
23    borrow: Cell<BorrowCounter>,
24    // Stores the location of the earliest currently active borrow.
25    // This gets updated whenever we go from having zero borrows
26    // to having a single borrow. When a borrow occurs, this gets included
27    // in the generated `BorrowError`/`BorrowMutError`
28    #[cfg(feature = "debug_refcell")]
29    borrowed_at: Cell<Option<&'static core::panic::Location<'static>>>,
30    // to make not sync since `impl<T: ?Sized> !Sync for RefCell<T> {}` is not possible on stable outside of core
31    marker: PhantomData<*mut T>,
32    value: UnsafeCell<T>,
33}
34
35/// An error returned by [`RefCell::try_borrow`].
36#[non_exhaustive]
37#[derive(Debug)]
38pub struct BorrowError {
39    #[cfg(feature = "debug_refcell")]
40    location: &'static core::panic::Location<'static>,
41}
42
43impl Display for BorrowError {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        #[cfg(feature = "debug_refcell")]
46        let res = write!(
47            f,
48            "RefCell already mutably borrowed; a previous borrow was at {}",
49            self.location
50        );
51
52        #[cfg(not(feature = "debug_refcell"))]
53        let res = Display::fmt("RefCell already mutably borrowed", f);
54
55        res
56    }
57}
58
59/// An error returned by [`RefCell::try_borrow_mut`].
60#[non_exhaustive]
61#[derive(Debug)]
62pub struct BorrowMutError {
63    #[cfg(feature = "debug_refcell")]
64    location: &'static core::panic::Location<'static>,
65}
66
67impl Display for BorrowMutError {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        #[cfg(feature = "debug_refcell")]
70        let res = write!(
71            f,
72            "RefCell already borrowed; a previous borrow was at {}",
73            self.location
74        );
75
76        #[cfg(not(feature = "debug_refcell"))]
77        let res = Display::fmt("RefCell already borrowed", f);
78
79        res
80    }
81}
82
83// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
84#[track_caller]
85#[cold]
86fn panic_already_borrowed(err: BorrowError) -> ! {
87    panic!("RefCell already borrowed: {err}")
88}
89
90// This ensures the panicking code is outlined from `borrow` for `RefCell`.
91#[track_caller]
92#[cold]
93fn panic_already_mutably_borrowed(err: BorrowMutError) -> ! {
94    panic!("RefCell already mutably borrowed: {err}")
95}
96
97// Positive values represent the number of `Ref` active. Negative values
98// represent the number of `RefMut` active. Multiple `RefMut`s can only be
99// active at a time if they refer to distinct, nonoverlapping components of a
100// `RefCell` (e.g., different ranges of a slice).
101//
102// `Ref` and `RefMut` are both two words in size, and so there will likely never
103// be enough `Ref`s or `RefMut`s in existence to overflow half of the `usize`
104// range. Thus, a `BorrowCounter` will probably never overflow or underflow.
105// However, this is not a guarantee, as a pathological program could repeatedly
106// create and then mem::forget `Ref`s or `RefMut`s. Thus, all code must
107// explicitly check for overflow and underflow in order to avoid unsafety, or at
108// least behave correctly in the event that overflow or underflow happens (e.g.,
109// see BorrowRef::new).
110type BorrowCounter = isize;
111const UNUSED: BorrowCounter = 0;
112
113#[inline(always)]
114const fn is_writing(x: BorrowCounter) -> bool {
115    x < UNUSED
116}
117
118#[inline(always)]
119const fn is_reading(x: BorrowCounter) -> bool {
120    x > UNUSED
121}
122
123impl<T> UncheckedRefCell<T> {
124    /// Creates a new `RefCell` containing `value`.
125    ///
126    /// # Examples
127    ///
128    /// ```
129    /// use unchecked_refcell::UncheckedRefCell;
130    ///
131    /// let c = UncheckedRefCell::new(5);
132    /// ```
133    #[inline]
134    pub const fn new(value: T) -> UncheckedRefCell<T> {
135        UncheckedRefCell {
136            value: UnsafeCell::new(value),
137            #[cfg(any(feature = "checked", debug_assertions))]
138            borrow: Cell::new(UNUSED),
139            marker: PhantomData,
140            #[cfg(feature = "debug_refcell")]
141            borrowed_at: Cell::new(None),
142        }
143    }
144
145    /// Consumes the `RefCell`, returning the wrapped value.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use unchecked_refcell::UncheckedRefCell;
151    ///
152    /// let c = UncheckedRefCell::new(5);
153    ///
154    /// let five = c.into_inner();
155    /// ```
156    #[inline]
157    pub fn into_inner(self) -> T {
158        // Since this function takes `self` (the `RefCell`) by value, the
159        // compiler statically verifies that it is not currently borrowed.
160        self.value.into_inner()
161    }
162
163    /// Replaces the wrapped value with a new one, returning the old value,
164    /// without deinitializing either one.
165    ///
166    /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html).
167    ///
168    /// # Panics
169    ///
170    /// Panics if the value is currently borrowed.
171    ///
172    /// # Examples
173    ///
174    /// ```
175    /// use unchecked_refcell::UncheckedRefCell;
176    /// let cell = UncheckedRefCell::new(5);
177    /// let old_value = cell.replace(6);
178    /// assert_eq!(old_value, 5);
179    /// assert_eq!(cell, UncheckedRefCell::new(6));
180    /// ```
181    #[track_caller]
182    pub fn replace(&self, t: T) -> T {
183        mem::replace(&mut self.borrow_mut(), t)
184    }
185
186    /// Replaces the wrapped value with a new one computed from `f`, returning
187    /// the old value, without deinitializing either one.
188    ///
189    /// # Panics
190    ///
191    /// Panics if the value is currently borrowed.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// use unchecked_refcell::UncheckedRefCell;
197    /// let cell = UncheckedRefCell::new(5);
198    /// let old_value = cell.replace_with(|&mut old| old + 1);
199    /// assert_eq!(old_value, 5);
200    /// assert_eq!(cell, UncheckedRefCell::new(6));
201    /// ```
202    #[inline]
203    #[track_caller]
204    pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
205        let mut_borrow = &mut *self.borrow_mut();
206        let replacement = f(mut_borrow);
207        mem::replace(mut_borrow, replacement)
208    }
209
210    /// Swaps the wrapped value of `self` with the wrapped value of `other`,
211    /// without deinitializing either one.
212    ///
213    /// This function corresponds to [`std::mem::swap`](../mem/fn.swap.html).
214    ///
215    /// # Panics
216    ///
217    /// Panics if the value in either `RefCell` is currently borrowed, or
218    /// if `self` and `other` point to the same `RefCell`.
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// use unchecked_refcell::UncheckedRefCell;
224    /// let c = UncheckedRefCell::new(5);
225    /// let d = UncheckedRefCell::new(6);
226    /// c.swap(&d);
227    /// assert_eq!(c, UncheckedRefCell::new(6));
228    /// assert_eq!(d, UncheckedRefCell::new(5));
229    /// ```
230    #[inline]
231    pub fn swap(&self, other: &Self) {
232        mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
233    }
234}
235
236impl<T: ?Sized> UncheckedRefCell<T> {
237    /// Immutably borrows the wrapped value.
238    ///
239    /// The borrow lasts until the returned `Ref` exits scope. Multiple
240    /// immutable borrows can be taken out at the same time.
241    ///
242    /// # Panics
243    ///
244    /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
245    /// [`try_borrow`](#method.try_borrow).
246    ///
247    /// # Examples
248    ///
249    /// ```
250    /// use unchecked_refcell::UncheckedRefCell;
251    ///
252    /// let c = UncheckedRefCell::new(5);
253    ///
254    /// let borrowed_five = c.borrow();
255    /// let borrowed_five2 = c.borrow();
256    /// ```
257    ///
258    /// An example of panic:
259    ///
260    /// ```should_panic
261    /// use unchecked_refcell::UncheckedRefCell;
262    ///
263    /// let c = UncheckedRefCell::new(5);
264    ///
265    /// let m = c.borrow_mut();
266    /// let b = c.borrow(); // this causes a panic
267    /// ```
268    #[inline]
269    #[track_caller]
270    pub fn borrow(&self) -> UncheckedRef<'_, T> {
271        match self.try_borrow() {
272            Ok(b) => b,
273            Err(err) => panic_already_borrowed(err),
274        }
275    }
276
277    /// Immutably borrows the wrapped value, returning an error if the value is currently mutably
278    /// borrowed.
279    ///
280    /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be
281    /// taken out at the same time.
282    ///
283    /// This is the non-panicking variant of [`borrow`](#method.borrow).
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// use unchecked_refcell::UncheckedRefCell;
289    ///
290    /// let c = UncheckedRefCell::new(5);
291    ///
292    /// {
293    ///     let m = c.borrow_mut();
294    ///     assert!(c.try_borrow().is_err());
295    /// }
296    ///
297    /// {
298    ///     let m = c.borrow();
299    ///     assert!(c.try_borrow().is_ok());
300    /// }
301    /// ```
302    #[inline]
303    pub fn try_borrow(&self) -> Result<UncheckedRef<'_, T>, BorrowError> {
304        #[cfg(any(feature = "checked", debug_assertions))]
305        match BorrowRef::new(&self.borrow) {
306            Some(b) => {
307                // SAFETY: `BorrowRef` ensures that there is only immutable access
308                // to the value while borrowed.
309                let value = unsafe { NonNull::new_unchecked(self.value.get()) };
310                Ok(UncheckedRef { value, borrow: b })
311            }
312            None => Err(BorrowError {
313                // If a borrow occurred, then we must already have an outstanding borrow,
314                // so `borrowed_at` will be `Some`
315                #[cfg(feature = "debug_refcell")]
316                location: self.borrowed_at.get().unwrap(),
317            }),
318        }
319        #[cfg(not(any(feature = "checked", debug_assertions)))]
320        {
321            // SAFETY: `BorrowRef` ensures that there is only immutable access
322            // to the value while borrowed.
323            let value = unsafe { NonNull::new_unchecked(self.value.get()) };
324            Ok(UncheckedRef {
325                value,
326                marker: PhantomData,
327            })
328        }
329    }
330
331    /// Mutably borrows the wrapped value.
332    ///
333    /// The borrow lasts until the returned `RefMut` or all `RefMut`s derived
334    /// from it exit scope. The value cannot be borrowed while this borrow is
335    /// active.
336    ///
337    /// # Panics
338    ///
339    /// Panics if the value is currently borrowed. For a non-panicking variant, use
340    /// [`try_borrow_mut`](#method.try_borrow_mut).
341    ///
342    /// # Examples
343    ///
344    /// ```
345    /// use unchecked_refcell::UncheckedRefCell;
346    ///
347    /// let c = UncheckedRefCell::new("hello".to_owned());
348    ///
349    /// *c.borrow_mut() = "bonjour".to_owned();
350    ///
351    /// assert_eq!(&*c.borrow(), "bonjour");
352    /// ```
353    ///
354    /// An example of panic:
355    ///
356    /// ```should_panic
357    /// use unchecked_refcell::UncheckedRefCell;
358    ///
359    /// let c = UncheckedRefCell::new(5);
360    /// let m = c.borrow();
361    ///
362    /// let b = c.borrow_mut(); // this causes a panic
363    /// ```
364    #[inline]
365    #[track_caller]
366    pub fn borrow_mut(&self) -> UncheckedRefMut<'_, T> {
367        match self.try_borrow_mut() {
368            Ok(b) => b,
369            Err(err) => panic_already_mutably_borrowed(err),
370        }
371    }
372
373    /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
374    ///
375    /// The borrow lasts until the returned `RefMut` or all `RefMut`s derived
376    /// from it exit scope. The value cannot be borrowed while this borrow is
377    /// active.
378    ///
379    /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
380    ///
381    /// # Examples
382    ///
383    /// ```
384    /// use unchecked_refcell::UncheckedRefCell;
385    ///
386    /// let c = UncheckedRefCell::new(5);
387    ///
388    /// {
389    ///     let m = c.borrow();
390    ///     assert!(c.try_borrow_mut().is_err());
391    /// }
392    ///
393    /// assert!(c.try_borrow_mut().is_ok());
394    /// ```
395    #[inline]
396    #[cfg_attr(feature = "debug_refcell", track_caller)]
397    pub fn try_borrow_mut(&self) -> Result<UncheckedRefMut<'_, T>, BorrowMutError> {
398        #[cfg(any(feature = "checked", debug_assertions))]
399        {
400            match BorrowRefMut::new(&self.borrow) {
401                Some(b) => {
402                    #[cfg(feature = "debug_refcell")]
403                    {
404                        self.borrowed_at
405                            .replace(Some(core::panic::Location::caller()));
406                    }
407
408                    // SAFETY: `BorrowRefMut` guarantees unique access.
409                    let value = unsafe { NonNull::new_unchecked(self.value.get()) };
410                    Ok(UncheckedRefMut {
411                        value,
412                        borrow: b,
413                        marker: PhantomData,
414                    })
415                }
416                None => Err(BorrowMutError {
417                    // If a borrow occurred, then we must already have an outstanding borrow,
418                    // so `borrowed_at` will be `Some`
419                    #[cfg(feature = "debug_refcell")]
420                    location: self.borrowed_at.get().unwrap(),
421                }),
422            }
423        }
424        #[cfg(not(any(feature = "checked", debug_assertions)))]
425        {
426            let value = unsafe { NonNull::new_unchecked(self.value.get()) };
427            Ok(UncheckedRefMut {
428                value,
429                marker: PhantomData,
430            })
431        }
432    }
433
434    /// Returns a raw pointer to the underlying data in this cell.
435    ///
436    /// # Examples
437    ///
438    /// ```
439    /// use unchecked_refcell::UncheckedRefCell;
440    ///
441    /// let c = UncheckedRefCell::new(5);
442    ///
443    /// let ptr = c.as_ptr();
444    /// ```
445    #[inline]
446    pub const fn as_ptr(&self) -> *mut T {
447        self.value.get()
448    }
449
450    /// Returns a mutable reference to the underlying data.
451    ///
452    /// Since this method borrows `RefCell` mutably, it is statically guaranteed
453    /// that no borrows to the underlying data exist. The dynamic checks inherent
454    /// in [`borrow_mut`] and most other methods of `RefCell` are therefore
455    /// unnecessary. Note that this method does not reset the borrowing state if borrows were previously leaked
456    /// (e.g., via [`forget()`] on a [`Ref`] or [`RefMut`]). For that purpose,
457    /// consider using the unstable [`undo_leak`] method.
458    ///
459    /// This method can only be called if `RefCell` can be mutably borrowed,
460    /// which in general is only the case directly after the `RefCell` has
461    /// been created. In these situations, skipping the aforementioned dynamic
462    /// borrowing checks may yield better ergonomics and runtime-performance.
463    ///
464    /// In most situations where `RefCell` is used, it can't be borrowed mutably.
465    /// Use [`borrow_mut`] to get mutable access to the underlying data then.
466    ///
467    /// [`borrow_mut`]: UncheckedRefCell::borrow_mut()
468    /// [`forget()`]: mem::forget
469    /// [`undo_leak`]: UncheckedRefCell::undo_leak()
470    ///
471    /// # Examples
472    ///
473    /// ```
474    /// use unchecked_refcell::UncheckedRefCell;
475    ///
476    /// let mut c = UncheckedRefCell::new(5);
477    /// *c.get_mut() += 1;
478    ///
479    /// assert_eq!(c, UncheckedRefCell::new(6));
480    /// ```
481    #[inline]
482    pub const fn get_mut(&mut self) -> &mut T {
483        self.value.get_mut()
484    }
485
486    /// Undo the effect of leaked guards on the borrow state of the `RefCell`.
487    ///
488    /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to
489    /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant
490    /// if some `Ref` or `RefMut` borrows have been leaked.
491    ///
492    /// [`get_mut`]: UncheckedRefCell::get_mut()
493    ///
494    /// # Examples
495    ///
496    /// ```
497    /// use unchecked_refcell::UncheckedRefCell;
498    ///
499    /// let mut c = UncheckedRefCell::new(0);
500    /// std::mem::forget(c.borrow_mut());
501    ///
502    /// assert!(c.try_borrow().is_err());
503    /// c.undo_leak();
504    /// assert!(c.try_borrow().is_ok());
505    /// ```
506    pub const fn undo_leak(&mut self) -> &mut T {
507        #[cfg(any(feature = "checked", debug_assertions))]
508        {
509            *self.borrow.get_mut() = UNUSED;
510        }
511        self.get_mut()
512    }
513
514    /// Immutably borrows the wrapped value, returning an error if the value is
515    /// currently mutably borrowed.
516    ///
517    /// # Safety
518    ///
519    /// Unlike `RefCell::borrow`, this method is unsafe because it does not
520    /// return a `Ref`, thus leaving the borrow flag untouched. Mutably
521    /// borrowing the `RefCell` while the reference returned by this method
522    /// is alive is undefined behavior.
523    ///
524    /// # Examples
525    ///
526    /// ```
527    /// use unchecked_refcell::UncheckedRefCell;
528    ///
529    /// let c = UncheckedRefCell::new(5);
530    ///
531    /// {
532    ///     let m = c.borrow_mut();
533    ///     assert!(unsafe { c.try_borrow_unguarded() }.is_err());
534    /// }
535    ///
536    /// {
537    ///     let m = c.borrow();
538    ///     assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
539    /// }
540    /// ```
541    #[inline]
542    pub const unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
543        #[cfg(any(feature = "checked", debug_assertions))]
544        {
545            if !is_writing(self.borrow.get()) {
546                // SAFETY: We check that nobody is actively writing now, but it is
547                // the caller's responsibility to ensure that nobody writes until
548                // the returned reference is no longer in use.
549                // Also, `self.value.get()` refers to the value owned by `self`
550                // and is thus guaranteed to be valid for the lifetime of `self`.
551                Ok(unsafe { &*self.value.get() })
552            } else {
553                Err(BorrowError {
554                    // If a borrow occurred, then we must already have an outstanding borrow,
555                    // so `borrowed_at` will be `Some`
556                    #[cfg(feature = "debug_refcell")]
557                    location: self.borrowed_at.get().unwrap(),
558                })
559            }
560        }
561        #[cfg(not(any(feature = "checked", debug_assertions)))]
562        Ok(unsafe { &*self.value.get() })
563    }
564}
565
566impl<T: Default> UncheckedRefCell<T> {
567    /// Takes the wrapped value, leaving `Default::default()` in its place.
568    ///
569    /// # Panics
570    ///
571    /// Panics if the value is currently borrowed.
572    ///
573    /// # Examples
574    ///
575    /// ```
576    /// use unchecked_refcell::UncheckedRefCell;
577    ///
578    /// let c = UncheckedRefCell::new(5);
579    /// let five = c.take();
580    ///
581    /// assert_eq!(five, 5);
582    /// assert_eq!(c.into_inner(), 0);
583    /// ```
584    pub fn take(&self) -> T {
585        self.replace(Default::default())
586    }
587}
588
589unsafe impl<T: ?Sized> Send for UncheckedRefCell<T> where T: Send {}
590
591impl<T: Clone> Clone for UncheckedRefCell<T> {
592    /// # Panics
593    ///
594    /// Panics if the value is currently mutably borrowed.
595    #[inline]
596    #[track_caller]
597    fn clone(&self) -> UncheckedRefCell<T> {
598        UncheckedRefCell::new(self.borrow().clone())
599    }
600
601    /// # Panics
602    ///
603    /// Panics if `source` is currently mutably borrowed.
604    #[inline]
605    #[track_caller]
606    fn clone_from(&mut self, source: &Self) {
607        self.get_mut().clone_from(&source.borrow())
608    }
609}
610
611impl<T: Default> Default for UncheckedRefCell<T> {
612    /// Creates a `RefCell<T>`, with the `Default` value for T.
613    #[inline]
614    fn default() -> UncheckedRefCell<T> {
615        UncheckedRefCell::new(Default::default())
616    }
617}
618
619impl<T: ?Sized + PartialEq> PartialEq for UncheckedRefCell<T> {
620    /// # Panics
621    ///
622    /// Panics if the value in either `RefCell` is currently mutably borrowed.
623    #[inline]
624    fn eq(&self, other: &UncheckedRefCell<T>) -> bool {
625        *self.borrow() == *other.borrow()
626    }
627}
628
629impl<T: ?Sized + Eq> Eq for UncheckedRefCell<T> {}
630
631impl<T: ?Sized + PartialOrd> PartialOrd for UncheckedRefCell<T> {
632    /// # Panics
633    ///
634    /// Panics if the value in either `RefCell` is currently mutably borrowed.
635    #[inline]
636    fn partial_cmp(&self, other: &UncheckedRefCell<T>) -> Option<Ordering> {
637        self.borrow().partial_cmp(&*other.borrow())
638    }
639
640    /// # Panics
641    ///
642    /// Panics if the value in either `RefCell` is currently mutably borrowed.
643    #[inline]
644    fn lt(&self, other: &UncheckedRefCell<T>) -> bool {
645        *self.borrow() < *other.borrow()
646    }
647
648    /// # Panics
649    ///
650    /// Panics if the value in either `RefCell` is currently mutably borrowed.
651    #[inline]
652    fn le(&self, other: &UncheckedRefCell<T>) -> bool {
653        *self.borrow() <= *other.borrow()
654    }
655
656    /// # Panics
657    ///
658    /// Panics if the value in either `RefCell` is currently mutably borrowed.
659    #[inline]
660    fn gt(&self, other: &UncheckedRefCell<T>) -> bool {
661        *self.borrow() > *other.borrow()
662    }
663
664    /// # Panics
665    ///
666    /// Panics if the value in either `RefCell` is currently mutably borrowed.
667    #[inline]
668    fn ge(&self, other: &UncheckedRefCell<T>) -> bool {
669        *self.borrow() >= *other.borrow()
670    }
671}
672
673impl<T: ?Sized + Ord> Ord for UncheckedRefCell<T> {
674    /// # Panics
675    ///
676    /// Panics if the value in either `RefCell` is currently mutably borrowed.
677    #[inline]
678    fn cmp(&self, other: &UncheckedRefCell<T>) -> Ordering {
679        self.borrow().cmp(&*other.borrow())
680    }
681}
682
683impl<T> From<T> for UncheckedRefCell<T> {
684    /// Creates a new `RefCell<T>` containing the given value.
685    fn from(t: T) -> UncheckedRefCell<T> {
686        UncheckedRefCell::new(t)
687    }
688}
689
690struct BorrowRef<'b> {
691    borrow: &'b Cell<BorrowCounter>,
692}
693
694impl<'b> BorrowRef<'b> {
695    #[inline]
696    const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> {
697        let b = borrow.get().wrapping_add(1);
698        if !is_reading(b) {
699            // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
700            // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read borrow
701            //    due to Rust's reference aliasing rules
702            // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed
703            //    into isize::MIN (the max amount of writing borrows) so we can't allow
704            //    an additional read borrow because isize can't represent so many read borrows
705            //    (this can only happen if you mem::forget more than a small constant amount of
706            //    `Ref`s, which is not good practice)
707            None
708        } else {
709            // Incrementing borrow can result in a reading value (> 0) in these cases:
710            // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
711            // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
712            //    is large enough to represent having one more read borrow
713            borrow.replace(b);
714            Some(BorrowRef { borrow })
715        }
716    }
717}
718
719impl Drop for BorrowRef<'_> {
720    #[inline]
721    fn drop(&mut self) {
722        let borrow = self.borrow.get();
723        debug_assert!(is_reading(borrow));
724        self.borrow.replace(borrow - 1);
725    }
726}
727
728impl Clone for BorrowRef<'_> {
729    #[inline]
730    fn clone(&self) -> Self {
731        // Since this Ref exists, we know the borrow flag
732        // is a reading borrow.
733        let borrow = self.borrow.get();
734        debug_assert!(is_reading(borrow));
735        // Prevent the borrow counter from overflowing into
736        // a writing borrow.
737        assert!(borrow != BorrowCounter::MAX);
738        self.borrow.replace(borrow + 1);
739        BorrowRef {
740            borrow: self.borrow,
741        }
742    }
743}
744
745/// Wraps a borrowed reference to a value in a `RefCell` box.
746/// A wrapper type for an immutably borrowed value from a `RefCell<T>`.
747///
748/// See the [module-level documentation](self) for more.
749pub struct UncheckedRef<'b, T: ?Sized + 'b> {
750    // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a
751    // `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
752    // `NonNull` is also covariant over `T`, just like we would have with `&T`.
753    value: NonNull<T>,
754    #[cfg(any(feature = "checked", debug_assertions))]
755    borrow: BorrowRef<'b>,
756    #[cfg(not(any(feature = "checked", debug_assertions)))]
757    marker: PhantomData<&'b ()>,
758}
759
760impl<T: ?Sized> Deref for UncheckedRef<'_, T> {
761    type Target = T;
762
763    #[inline]
764    fn deref(&self) -> &T {
765        // SAFETY: the value is accessible as long as we hold our borrow.
766        unsafe { self.value.as_ref() }
767    }
768}
769
770impl<'b, T: ?Sized> UncheckedRef<'b, T> {
771    /// Copies a `Ref`.
772    ///
773    /// The `RefCell` is already immutably borrowed, so this cannot fail.
774    ///
775    /// This is an associated function that needs to be used as
776    /// `Ref::clone(...)`. A `Clone` implementation or a method would interfere
777    /// with the widespread use of `r.borrow().clone()` to clone the contents of
778    /// a `RefCell`.
779    #[must_use]
780    #[inline]
781    pub fn clone(orig: &UncheckedRef<'b, T>) -> UncheckedRef<'b, T> {
782        UncheckedRef {
783            value: orig.value,
784            #[cfg(any(feature = "checked", debug_assertions))]
785            borrow: orig.borrow.clone(),
786            #[cfg(not(any(feature = "checked", debug_assertions)))]
787            marker: PhantomData,
788        }
789    }
790
791    /// Makes a new `Ref` for a component of the borrowed data.
792    ///
793    /// The `RefCell` is already immutably borrowed, so this cannot fail.
794    ///
795    /// This is an associated function that needs to be used as `Ref::map(...)`.
796    /// A method would interfere with methods of the same name on the contents
797    /// of a `RefCell` used through `Deref`.
798    ///
799    /// # Examples
800    ///
801    /// ```
802    /// use unchecked_refcell::{UncheckedRefCell, Ref};
803    ///
804    /// let c = UncheckedRefCell::new((5, 'b'));
805    /// let b1: Ref<'_, (u32, char)> = c.borrow();
806    /// let b2: Ref<'_, u32> = Ref::map(b1, |t| &t.0);
807    /// assert_eq!(*b2, 5)
808    /// ```
809    #[inline]
810    pub fn map<U: ?Sized, F>(orig: UncheckedRef<'b, T>, f: F) -> UncheckedRef<'b, U>
811    where
812        F: FnOnce(&T) -> &U,
813    {
814        UncheckedRef {
815            value: NonNull::from(f(&*orig)),
816            #[cfg(any(feature = "checked", debug_assertions))]
817            borrow: orig.borrow,
818            #[cfg(not(any(feature = "checked", debug_assertions)))]
819            marker: PhantomData,
820        }
821    }
822
823    /// Makes a new `Ref` for an optional component of the borrowed data. The
824    /// original guard is returned as an `Err(..)` if the closure returns
825    /// `None`.
826    ///
827    /// The `RefCell` is already immutably borrowed, so this cannot fail.
828    ///
829    /// This is an associated function that needs to be used as
830    /// `Ref::filter_map(...)`. A method would interfere with methods of the same
831    /// name on the contents of a `RefCell` used through `Deref`.
832    ///
833    /// # Examples
834    ///
835    /// ```
836    /// use unchecked_refcell::{UncheckedRefCell, Ref};
837    ///
838    /// let c = UncheckedRefCell::new(vec![1, 2, 3]);
839    /// let b1: Ref<'_, Vec<u32>> = c.borrow();
840    /// let b2: Result<Ref<'_, u32>, _> = Ref::filter_map(b1, |v| v.get(1));
841    /// assert_eq!(*b2.unwrap(), 2);
842    /// ```
843    #[inline]
844    pub fn filter_map<U: ?Sized, F>(orig: UncheckedRef<'b, T>, f: F) -> Result<UncheckedRef<'b, U>, Self>
845    where
846        F: FnOnce(&T) -> Option<&U>,
847    {
848        match f(&*orig) {
849            Some(value) => Ok(UncheckedRef {
850                value: NonNull::from(value),
851                #[cfg(any(feature = "checked", debug_assertions))]
852                borrow: orig.borrow,
853                #[cfg(not(any(feature = "checked", debug_assertions)))]
854                marker: PhantomData,
855            }),
856            None => Err(orig),
857        }
858    }
859
860    /// Tries to makes a new `Ref` for a component of the borrowed data.
861    /// On failure, the original guard is returned alongside with the error
862    /// returned by the closure.
863    ///
864    /// The `RefCell` is already immutably borrowed, so this cannot fail.
865    ///
866    /// This is an associated function that needs to be used as
867    /// `Ref::try_map(...)`. A method would interfere with methods of the same
868    /// name on the contents of a `RefCell` used through `Deref`.
869    ///
870    /// # Examples
871    ///
872    /// ```
873    /// use unchecked_refcell::{UncheckedRefCell, Ref};
874    /// use std::str::{from_utf8, Utf8Error};
875    ///
876    /// let c = UncheckedRefCell::new(vec![0xF0, 0x9F, 0xA6 ,0x80]);
877    /// let b1: Ref<'_, Vec<u8>> = c.borrow();
878    /// let b2: Result<Ref<'_, str>, _> = Ref::try_map(b1, |v| from_utf8(v));
879    /// assert_eq!(&*b2.unwrap(), "🦀");
880    ///
881    /// let c = UncheckedRefCell::new(vec![0xF0, 0x9F, 0xA6]);
882    /// let b1: Ref<'_, Vec<u8>> = c.borrow();
883    /// let b2: Result<_, (Ref<'_, Vec<u8>>, Utf8Error)> = Ref::try_map(b1, |v| from_utf8(v));
884    /// let (b3, e) = b2.unwrap_err();
885    /// assert_eq!(*b3, vec![0xF0, 0x9F, 0xA6]);
886    /// assert_eq!(e.valid_up_to(), 0);
887    /// ```
888    #[inline]
889    pub fn try_map<U: ?Sized, E>(
890        orig: UncheckedRef<'b, T>,
891        f: impl FnOnce(&T) -> Result<&U, E>,
892    ) -> Result<UncheckedRef<'b, U>, (Self, E)> {
893        match f(&*orig) {
894            Ok(value) => Ok(UncheckedRef {
895                value: NonNull::from(value),
896                #[cfg(any(feature = "checked", debug_assertions))]
897                borrow: orig.borrow,
898                #[cfg(not(any(feature = "checked", debug_assertions)))]
899                marker: PhantomData,
900            }),
901            Err(e) => Err((orig, e)),
902        }
903    }
904
905    /// Splits a `Ref` into multiple `Ref`s for different components of the
906    /// borrowed data.
907    ///
908    /// The `RefCell` is already immutably borrowed, so this cannot fail.
909    ///
910    /// This is an associated function that needs to be used as
911    /// `Ref::map_split(...)`. A method would interfere with methods of the same
912    /// name on the contents of a `RefCell` used through `Deref`.
913    ///
914    /// # Examples
915    ///
916    /// ```
917    /// use unchecked_refcell::{UncheckedRefCell, Ref};
918    ///
919    /// let cell = UncheckedRefCell::new([1, 2, 3, 4]);
920    /// let borrow = cell.borrow();
921    /// let (begin, end) = Ref::map_split(borrow, |slice| slice.split_at(2));
922    /// assert_eq!(*begin, [1, 2]);
923    /// assert_eq!(*end, [3, 4]);
924    /// ```
925    #[inline]
926    pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: UncheckedRef<'b, T>, f: F) -> (UncheckedRef<'b, U>, UncheckedRef<'b, V>)
927    where
928        F: FnOnce(&T) -> (&U, &V),
929    {
930        let (a, b) = f(&*orig);
931        #[cfg(any(feature = "checked", debug_assertions))]
932        let borrow = orig.borrow.clone();
933        (
934            UncheckedRef {
935                value: NonNull::from(a),
936                #[cfg(any(feature = "checked", debug_assertions))]
937                borrow,
938                #[cfg(not(any(feature = "checked", debug_assertions)))]
939                marker: PhantomData,
940            },
941            UncheckedRef {
942                value: NonNull::from(b),
943                #[cfg(any(feature = "checked", debug_assertions))]
944                borrow: orig.borrow,
945                #[cfg(not(any(feature = "checked", debug_assertions)))]
946                marker: PhantomData,
947            },
948        )
949    }
950
951    /// Converts into a reference to the underlying data.
952    ///
953    /// The underlying `RefCell` can never be mutably borrowed from again and will always appear
954    /// already immutably borrowed. It is not a good idea to leak more than a constant number of
955    /// references. The `RefCell` can be immutably borrowed again if only a smaller number of leaks
956    /// have occurred in total.
957    ///
958    /// This is an associated function that needs to be used as
959    /// `Ref::leak(...)`. A method would interfere with methods of the
960    /// same name on the contents of a `RefCell` used through `Deref`.
961    ///
962    /// # Examples
963    ///
964    /// ```
965    /// use unchecked_refcell::{UncheckedRefCell, Ref};
966    /// let cell = UncheckedRefCell::new(0);
967    ///
968    /// let value = Ref::leak(cell.borrow());
969    /// assert_eq!(*value, 0);
970    ///
971    /// assert!(cell.try_borrow().is_ok());
972    /// assert!(cell.try_borrow_mut().is_err());
973    /// ```
974    pub fn leak(orig: UncheckedRef<'b, T>) -> &'b T {
975        // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
976        // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
977        // unique reference to the borrowed RefCell. No further mutable references can be created
978        // from the original cell.
979        #[cfg(any(feature = "checked", debug_assertions))]
980        mem::forget(orig.borrow);
981        // SAFETY: after forgetting, we can form a reference for the rest of lifetime `'b`.
982        unsafe { orig.value.as_ref() }
983    }
984}
985
986impl<T: ?Sized + fmt::Display> fmt::Display for UncheckedRef<'_, T> {
987    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
988        (**self).fmt(f)
989    }
990}
991
992impl<'b, T: ?Sized> UncheckedRefMut<'b, T> {
993    /// Makes a new `RefMut` for a component of the borrowed data, e.g., an enum
994    /// variant.
995    ///
996    /// The `RefCell` is already mutably borrowed, so this cannot fail.
997    ///
998    /// This is an associated function that needs to be used as
999    /// `RefMut::map(...)`. A method would interfere with methods of the same
1000    /// name on the contents of a `RefCell` used through `Deref`.
1001    ///
1002    /// # Examples
1003    ///
1004    /// ```
1005    /// use unchecked_refcell::{UncheckedRefCell, RefMut};
1006    ///
1007    /// let c = UncheckedRefCell::new((5, 'b'));
1008    /// {
1009    ///     let b1: RefMut<'_, (u32, char)> = c.borrow_mut();
1010    ///     let mut b2: RefMut<'_, u32> = RefMut::map(b1, |t| &mut t.0);
1011    ///     assert_eq!(*b2, 5);
1012    ///     *b2 = 42;
1013    /// }
1014    /// assert_eq!(*c.borrow(), (42, 'b'));
1015    /// ```
1016    #[inline]
1017    pub fn map<U: ?Sized, F>(mut orig: UncheckedRefMut<'b, T>, f: F) -> UncheckedRefMut<'b, U>
1018    where
1019        F: FnOnce(&mut T) -> &mut U,
1020    {
1021        let value = NonNull::from(f(&mut *orig));
1022        UncheckedRefMut {
1023            value,
1024            #[cfg(any(feature = "checked", debug_assertions))]
1025            borrow: orig.borrow,
1026            marker: PhantomData,
1027        }
1028    }
1029
1030    /// Makes a new `RefMut` for an optional component of the borrowed data. The
1031    /// original guard is returned as an `Err(..)` if the closure returns
1032    /// `None`.
1033    ///
1034    /// The `RefCell` is already mutably borrowed, so this cannot fail.
1035    ///
1036    /// This is an associated function that needs to be used as
1037    /// `RefMut::filter_map(...)`. A method would interfere with methods of the
1038    /// same name on the contents of a `RefCell` used through `Deref`.
1039    ///
1040    /// # Examples
1041    ///
1042    /// ```
1043    /// use unchecked_refcell::{UncheckedRefCell, RefMut};
1044    ///
1045    /// let c = UncheckedRefCell::new(vec![1, 2, 3]);
1046    ///
1047    /// {
1048    ///     let b1: RefMut<'_, Vec<u32>> = c.borrow_mut();
1049    ///     let mut b2: Result<RefMut<'_, u32>, _> = RefMut::filter_map(b1, |v| v.get_mut(1));
1050    ///
1051    ///     if let Ok(mut b2) = b2 {
1052    ///         *b2 += 2;
1053    ///     }
1054    /// }
1055    ///
1056    /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
1057    /// ```
1058    #[inline]
1059    pub fn filter_map<U: ?Sized, F>(mut orig: UncheckedRefMut<'b, T>, f: F) -> Result<UncheckedRefMut<'b, U>, Self>
1060    where
1061        F: FnOnce(&mut T) -> Option<&mut U>,
1062    {
1063        // SAFETY: function holds onto an exclusive reference for the duration
1064        // of its call through `orig`, and the pointer is only de-referenced
1065        // inside of the function call never allowing the exclusive reference to
1066        // escape.
1067        match f(&mut *orig) {
1068            Some(value) => Ok(UncheckedRefMut {
1069                value: NonNull::from(value),
1070                #[cfg(any(feature = "checked", debug_assertions))]
1071                borrow: orig.borrow,
1072                marker: PhantomData,
1073            }),
1074            None => Err(orig),
1075        }
1076    }
1077
1078    /// Tries to makes a new `RefMut` for a component of the borrowed data.
1079    /// On failure, the original guard is returned alongside with the error
1080    /// returned by the closure.
1081    ///
1082    /// The `RefCell` is already mutably borrowed, so this cannot fail.
1083    ///
1084    /// This is an associated function that needs to be used as
1085    /// `RefMut::try_map(...)`. A method would interfere with methods of the same
1086    /// name on the contents of a `RefCell` used through `Deref`.
1087    ///
1088    /// # Examples
1089    ///
1090    /// ```
1091    /// use unchecked_refcell::{UncheckedRefCell, RefMut};
1092    /// use std::str::{from_utf8_mut, Utf8Error};
1093    ///
1094    /// let c = UncheckedRefCell::new(vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);
1095    /// {
1096    ///     let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1097    ///     let b2: Result<RefMut<'_, str>, _> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1098    ///     let mut b2 = b2.unwrap();
1099    ///     assert_eq!(&*b2, "hello");
1100    ///     b2.make_ascii_uppercase();
1101    /// }
1102    /// assert_eq!(*c.borrow(), "HELLO".as_bytes());
1103    ///
1104    /// let c = UncheckedRefCell::new(vec![0xFF]);
1105    /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1106    /// let b2: Result<_, (RefMut<'_, Vec<u8>>, Utf8Error)> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1107    /// let (b3, e) = b2.unwrap_err();
1108    /// assert_eq!(*b3, vec![0xFF]);
1109    /// assert_eq!(e.valid_up_to(), 0);
1110    /// ```
1111    #[inline]
1112    pub fn try_map<U: ?Sized, E>(
1113        mut orig: UncheckedRefMut<'b, T>,
1114        f: impl FnOnce(&mut T) -> Result<&mut U, E>,
1115    ) -> Result<UncheckedRefMut<'b, U>, (Self, E)> {
1116        // SAFETY: function holds onto an exclusive reference for the duration
1117        // of its call through `orig`, and the pointer is only de-referenced
1118        // inside of the function call never allowing the exclusive reference to
1119        // escape.
1120        match f(&mut *orig) {
1121            Ok(value) => Ok(UncheckedRefMut {
1122                value: NonNull::from(value),
1123                #[cfg(any(feature = "checked", debug_assertions))]
1124                borrow: orig.borrow,
1125                marker: PhantomData,
1126            }),
1127            Err(e) => Err((orig, e)),
1128        }
1129    }
1130
1131    /// Splits a `RefMut` into multiple `RefMut`s for different components of the
1132    /// borrowed data.
1133    ///
1134    /// The underlying `RefCell` will remain mutably borrowed until both
1135    /// returned `RefMut`s go out of scope.
1136    ///
1137    /// The `RefCell` is already mutably borrowed, so this cannot fail.
1138    ///
1139    /// This is an associated function that needs to be used as
1140    /// `RefMut::map_split(...)`. A method would interfere with methods of the
1141    /// same name on the contents of a `RefCell` used through `Deref`.
1142    ///
1143    /// # Examples
1144    ///
1145    /// ```
1146    /// use unchecked_refcell::{UncheckedRefCell, RefMut};
1147    ///
1148    /// let cell = UncheckedRefCell::new([1, 2, 3, 4]);
1149    /// let borrow = cell.borrow_mut();
1150    /// let (mut begin, mut end) = RefMut::map_split(borrow, |slice| slice.split_at_mut(2));
1151    /// assert_eq!(*begin, [1, 2]);
1152    /// assert_eq!(*end, [3, 4]);
1153    /// begin.copy_from_slice(&[4, 3]);
1154    /// end.copy_from_slice(&[2, 1]);
1155    /// ```
1156    #[inline]
1157    pub fn map_split<U: ?Sized, V: ?Sized, F>(
1158        mut orig: UncheckedRefMut<'b, T>,
1159        f: F,
1160    ) -> (UncheckedRefMut<'b, U>, UncheckedRefMut<'b, V>)
1161    where
1162        F: FnOnce(&mut T) -> (&mut U, &mut V),
1163    {
1164        #[cfg(any(feature = "checked", debug_assertions))]
1165        let borrow = orig.borrow.clone();
1166        let (a, b) = f(&mut *orig);
1167        (
1168            UncheckedRefMut {
1169                value: NonNull::from(a),
1170                #[cfg(any(feature = "checked", debug_assertions))]
1171                borrow,
1172                marker: PhantomData,
1173            },
1174            UncheckedRefMut {
1175                value: NonNull::from(b),
1176                #[cfg(any(feature = "checked", debug_assertions))]
1177                borrow: orig.borrow,
1178                marker: PhantomData,
1179            },
1180        )
1181    }
1182
1183    /// Converts into a mutable reference to the underlying data.
1184    ///
1185    /// The underlying `RefCell` can not be borrowed from again and will always appear already
1186    /// mutably borrowed, making the returned reference the only to the interior.
1187    ///
1188    /// This is an associated function that needs to be used as
1189    /// `RefMut::leak(...)`. A method would interfere with methods of the
1190    /// same name on the contents of a `RefCell` used through `Deref`.
1191    ///
1192    /// # Examples
1193    ///
1194    /// ```
1195    /// use unchecked_refcell::{UncheckedRefCell, RefMut};
1196    /// let cell = UncheckedRefCell::new(0);
1197    ///
1198    /// let value = RefMut::leak(cell.borrow_mut());
1199    /// assert_eq!(*value, 0);
1200    /// *value = 1;
1201    ///
1202    /// assert!(cell.try_borrow_mut().is_err());
1203    /// ```
1204    pub fn leak(mut orig: UncheckedRefMut<'b, T>) -> &'b mut T {
1205        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
1206        // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
1207        // require a unique reference to the borrowed RefCell. No further references can be created
1208        // from the original cell within that lifetime, making the current borrow the only
1209        // reference for the remaining lifetime.
1210        #[cfg(any(feature = "checked", debug_assertions))]
1211        mem::forget(orig.borrow);
1212        // SAFETY: after forgetting, we can form a reference for the rest of lifetime `'b`.
1213        unsafe { orig.value.as_mut() }
1214    }
1215}
1216
1217struct BorrowRefMut<'b> {
1218    borrow: &'b Cell<BorrowCounter>,
1219}
1220
1221impl Drop for BorrowRefMut<'_> {
1222    #[inline]
1223    fn drop(&mut self) {
1224        let borrow = self.borrow.get();
1225        debug_assert!(is_writing(borrow));
1226        self.borrow.replace(borrow + 1);
1227    }
1228}
1229
1230impl<'b> BorrowRefMut<'b> {
1231    #[inline]
1232    const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRefMut<'b>> {
1233        // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
1234        // mutable reference, and so there must currently be no existing
1235        // references. Thus, while clone increments the mutable refcount, here
1236        // we explicitly only allow going from UNUSED to UNUSED - 1.
1237        match borrow.get() {
1238            UNUSED => {
1239                borrow.replace(UNUSED - 1);
1240                Some(BorrowRefMut { borrow })
1241            }
1242            _ => None,
1243        }
1244    }
1245
1246    // Clones a `BorrowRefMut`.
1247    //
1248    // This is only valid if each `BorrowRefMut` is used to track a mutable
1249    // reference to a distinct, nonoverlapping range of the original object.
1250    // This isn't in a Clone impl so that code doesn't call this implicitly.
1251    #[inline]
1252    fn clone(&self) -> BorrowRefMut<'b> {
1253        let borrow = self.borrow.get();
1254        debug_assert!(is_writing(borrow));
1255        // Prevent the borrow counter from underflowing.
1256        assert!(borrow != BorrowCounter::MIN);
1257        self.borrow.set(borrow - 1);
1258        BorrowRefMut {
1259            borrow: self.borrow,
1260        }
1261    }
1262}
1263
1264/// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
1265///
1266/// See the [module-level documentation](self) for more.
1267pub struct UncheckedRefMut<'b, T: ?Sized + 'b> {
1268    // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a
1269    // `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops.
1270    value: NonNull<T>,
1271    #[cfg(any(feature = "checked", debug_assertions))]
1272    borrow: BorrowRefMut<'b>,
1273    // `NonNull` is covariant over `T`, so we need to reintroduce invariance.
1274    marker: PhantomData<&'b mut T>,
1275}
1276
1277impl<T: ?Sized> Deref for UncheckedRefMut<'_, T> {
1278    type Target = T;
1279
1280    #[inline]
1281    fn deref(&self) -> &T {
1282        // SAFETY: the value is accessible as long as we hold our borrow.
1283        unsafe { self.value.as_ref() }
1284    }
1285}
1286
1287impl<T: ?Sized> DerefMut for UncheckedRefMut<'_, T> {
1288    #[inline]
1289    fn deref_mut(&mut self) -> &mut T {
1290        // SAFETY: the value is accessible as long as we hold our borrow.
1291        unsafe { self.value.as_mut() }
1292    }
1293}
1294
1295impl<T: ?Sized + fmt::Display> fmt::Display for UncheckedRefMut<'_, T> {
1296    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1297        (**self).fmt(f)
1298    }
1299}
1300
1301//************************************************************************//
1302
1303impl<T: ?Sized + Debug> Debug for UncheckedRefCell<T> {
1304    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1305        let mut d = f.debug_struct("RefCell");
1306        match self.try_borrow() {
1307            Ok(borrow) => d.field("value", &borrow),
1308            Err(_) => d.field("value", &format_args!("<borrowed>")),
1309        };
1310        d.finish()
1311    }
1312}
1313
1314impl<T: ?Sized + Debug> Debug for UncheckedRef<'_, T> {
1315    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1316        Debug::fmt(&**self, f)
1317    }
1318}
1319
1320impl<T: ?Sized + Debug> Debug for UncheckedRefMut<'_, T> {
1321    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1322        Debug::fmt(&*(self.deref()), f)
1323    }
1324}