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