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}