unchecked_refcell/
lib.rs

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