rs_matter/utils/cell.rs
1/*
2 *
3 * Copyright (c) 2024-2026 Project CHIP Authors
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18//! A modification of the Rust `RefCell` type which provides in-place initialization
19//! via `RefCell::init`.
20//!
21//! NOTE: TEMPORARY and subject to removal once all Matter state is hidden behind
22//! a `blmutex::Mutex` in future.
23
24#![allow(unexpected_cfgs)]
25#![allow(clippy::should_implement_trait)]
26
27use core::cell::{Cell, UnsafeCell};
28use core::cmp::Ordering;
29use core::fmt::{self, Debug, Display};
30use core::marker::PhantomData;
31use core::mem;
32use core::ops::{Deref, DerefMut};
33use core::ptr::NonNull;
34
35use super::init::{init, Init, UnsafeCellInit};
36
37/// A mutable memory location with dynamically checked borrow rules
38///
39/// See the [module-level documentation](self) for more.
40pub struct RefCell<T: ?Sized> {
41 borrow: Cell<BorrowFlag>,
42 // Stores the location of the earliest currently active borrow.
43 // This gets updated whenever we go from having zero borrows
44 // to having a single borrow. When a borrow occurs, this gets included
45 // in the generated `BorrowError`/`BorrowMutError`
46 #[cfg(feature = "debug_refcell")]
47 borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
48 _not_sync: PhantomData<*const ()>,
49 value: UnsafeCell<T>,
50}
51
52/// An error returned by [`RefCell::try_borrow`].
53#[non_exhaustive]
54pub struct BorrowError {
55 #[cfg(feature = "debug_refcell")]
56 location: &'static crate::panic::Location<'static>,
57}
58
59impl Debug for BorrowError {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 let mut builder = f.debug_struct("BorrowError");
62
63 #[cfg(feature = "debug_refcell")]
64 builder.field("location", self.location);
65
66 builder.finish()
67 }
68}
69
70impl Display for BorrowError {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 Display::fmt("already mutably borrowed", f)
73 }
74}
75
76#[cfg(feature = "defmt")]
77impl defmt::Format for BorrowError {
78 fn format(&self, f: defmt::Formatter<'_>) {
79 defmt::write!(f, "already mutably borrowed")
80 }
81}
82
83/// An error returned by [`RefCell::try_borrow_mut`].
84#[non_exhaustive]
85pub struct BorrowMutError {
86 #[cfg(feature = "debug_refcell")]
87 location: &'static crate::panic::Location<'static>,
88}
89
90impl Debug for BorrowMutError {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 let mut builder = f.debug_struct("BorrowMutError");
93
94 #[cfg(feature = "debug_refcell")]
95 builder.field("location", self.location);
96
97 builder.finish()
98 }
99}
100
101impl Display for BorrowMutError {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 Display::fmt("already borrowed", f)
104 }
105}
106
107#[cfg(feature = "defmt")]
108impl defmt::Format for BorrowMutError {
109 fn format(&self, f: defmt::Formatter<'_>) {
110 defmt::write!(f, "already borrowed")
111 }
112}
113
114// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
115#[inline(never)]
116#[track_caller]
117#[cold]
118fn panic_already_borrowed(err: BorrowMutError) -> ! {
119 panic!("already borrowed: {:?}", err)
120}
121
122// This ensures the panicking code is outlined from `borrow` for `RefCell`.
123#[inline(never)]
124#[track_caller]
125#[cold]
126fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
127 panic!("already mutably borrowed: {:?}", err)
128}
129
130// Positive values represent the number of `Ref` active. Negative values
131// represent the number of `RefMut` active. Multiple `RefMut`s can only be
132// active at a time if they refer to distinct, nonoverlapping components of a
133// `RefCell` (e.g., different ranges of a slice).
134//
135// `Ref` and `RefMut` are both two words in size, and so there will likely never
136// be enough `Ref`s or `RefMut`s in existence to overflow half of the `usize`
137// range. Thus, a `BorrowFlag` will probably never overflow or underflow.
138// However, this is not a guarantee, as a pathological program could repeatedly
139// create and then mem::forget `Ref`s or `RefMut`s. Thus, all code must
140// explicitly check for overflow and underflow in order to avoid unsafety, or at
141// least behave correctly in the event that overflow or underflow happens (e.g.,
142// see BorrowRef::new).
143type BorrowFlag = isize;
144const UNUSED: BorrowFlag = 0;
145
146#[inline(always)]
147fn is_writing(x: BorrowFlag) -> bool {
148 x < UNUSED
149}
150
151#[inline(always)]
152fn is_reading(x: BorrowFlag) -> bool {
153 x > UNUSED
154}
155
156impl<T> RefCell<T> {
157 /// Creates a new `RefCell` containing `value`.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// use std::cell::RefCell;
163 ///
164 /// let c = RefCell::new(5);
165 /// ```
166 #[inline]
167 pub const fn new(value: T) -> RefCell<T> {
168 RefCell {
169 value: UnsafeCell::new(value),
170 borrow: Cell::new(UNUSED),
171 #[cfg(feature = "debug_refcell")]
172 borrowed_at: Cell::new(None),
173 _not_sync: PhantomData,
174 }
175 }
176
177 /// Creates a new `RefCell` in-place initializer
178 /// by using the given value initializer.
179 pub fn init<I: Init<T>>(value: I) -> impl Init<Self> {
180 init!(Self {
181 value <- UnsafeCell::init(value),
182 borrow: Cell::new(UNUSED),
183 // #[cfg(feature = "debug_refcell")]
184 // borrowed_at: Cell::new(None),
185 _not_sync: PhantomData,
186 })
187 }
188
189 /// Consumes the `RefCell`, returning the wrapped value.
190 ///
191 /// # Examples
192 ///
193 /// ```
194 /// use std::cell::RefCell;
195 ///
196 /// let c = RefCell::new(5);
197 ///
198 /// let five = c.into_inner();
199 /// ```
200 #[inline]
201 pub fn into_inner(self) -> T {
202 // Since this function takes `self` (the `RefCell`) by value, the
203 // compiler statically verifies that it is not currently borrowed.
204 self.value.into_inner()
205 }
206
207 /// Replaces the wrapped value with a new one, returning the old value,
208 /// without deinitializing either one.
209 ///
210 /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html).
211 ///
212 /// # Panics
213 ///
214 /// Panics if the value is currently borrowed.
215 ///
216 /// # Examples
217 ///
218 /// ```
219 /// use std::cell::RefCell;
220 /// let cell = RefCell::new(5);
221 /// let old_value = cell.replace(6);
222 /// assert_eq!(old_value, 5);
223 /// assert_eq!(cell, RefCell::new(6));
224 /// ```
225 #[inline]
226 #[track_caller]
227 pub fn replace(&self, t: T) -> T {
228 mem::replace(&mut *self.borrow_mut(), t)
229 }
230
231 /// Replaces the wrapped value with a new one computed from `f`, returning
232 /// the old value, without deinitializing either one.
233 ///
234 /// # Panics
235 ///
236 /// Panics if the value is currently borrowed.
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// use std::cell::RefCell;
242 /// let cell = RefCell::new(5);
243 /// let old_value = cell.replace_with(|&mut old| old + 1);
244 /// assert_eq!(old_value, 5);
245 /// assert_eq!(cell, RefCell::new(6));
246 /// ```
247 #[inline]
248 #[track_caller]
249 pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
250 let mut_borrow = &mut *self.borrow_mut();
251 let replacement = f(mut_borrow);
252 mem::replace(mut_borrow, replacement)
253 }
254
255 /// Swaps the wrapped value of `self` with the wrapped value of `other`,
256 /// without deinitializing either one.
257 ///
258 /// This function corresponds to [`std::mem::swap`](../mem/fn.swap.html).
259 ///
260 /// # Panics
261 ///
262 /// Panics if the value in either `RefCell` is currently borrowed, or
263 /// if `self` and `other` point to the same `RefCell`.
264 ///
265 /// # Examples
266 ///
267 /// ```
268 /// use std::cell::RefCell;
269 /// let c = RefCell::new(5);
270 /// let d = RefCell::new(6);
271 /// c.swap(&d);
272 /// assert_eq!(c, RefCell::new(6));
273 /// assert_eq!(d, RefCell::new(5));
274 /// ```
275 #[inline]
276 pub fn swap(&self, other: &Self) {
277 mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
278 }
279}
280
281impl<T: ?Sized> RefCell<T> {
282 /// Immutably borrows the wrapped value.
283 ///
284 /// The borrow lasts until the returned `Ref` exits scope. Multiple
285 /// immutable borrows can be taken out at the same time.
286 ///
287 /// # Panics
288 ///
289 /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
290 /// [`try_borrow`](#method.try_borrow).
291 ///
292 /// # Examples
293 ///
294 /// ```
295 /// use std::cell::RefCell;
296 ///
297 /// let c = RefCell::new(5);
298 ///
299 /// let borrowed_five = c.borrow();
300 /// let borrowed_five2 = c.borrow();
301 /// ```
302 ///
303 /// An example of panic:
304 ///
305 /// ```should_panic
306 /// use std::cell::RefCell;
307 ///
308 /// let c = RefCell::new(5);
309 ///
310 /// let m = c.borrow_mut();
311 /// let b = c.borrow(); // this causes a panic
312 /// ```
313 #[inline]
314 #[track_caller]
315 pub fn borrow(&self) -> Ref<'_, T> {
316 match self.try_borrow() {
317 Ok(b) => b,
318 Err(err) => panic_already_mutably_borrowed(err),
319 }
320 }
321
322 /// Immutably borrows the wrapped value, returning an error if the value is currently mutably
323 /// borrowed.
324 ///
325 /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be
326 /// taken out at the same time.
327 ///
328 /// This is the non-panicking variant of [`borrow`](#method.borrow).
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// use std::cell::RefCell;
334 ///
335 /// let c = RefCell::new(5);
336 ///
337 /// {
338 /// let m = c.borrow_mut();
339 /// assert!(c.try_borrow().is_err());
340 /// }
341 ///
342 /// {
343 /// let m = c.borrow();
344 /// assert!(c.try_borrow().is_ok());
345 /// }
346 /// ```
347 #[inline]
348 pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
349 match BorrowRef::new(&self.borrow) {
350 Some(b) => {
351 #[cfg(feature = "debug_refcell")]
352 {
353 // `borrowed_at` is always the *first* active borrow
354 if b.borrow.get() == 1 {
355 self.borrowed_at.set(Some(crate::panic::Location::caller()));
356 }
357 }
358
359 // SAFETY: `BorrowRef` ensures that there is only immutable access
360 // to the value while borrowed.
361 let value = unsafe { NonNull::new_unchecked(self.value.get()) };
362 Ok(Ref { value, borrow: b })
363 }
364 None => Err(BorrowError {
365 // If a borrow occurred, then we must already have an outstanding borrow,
366 // so `borrowed_at` will be `Some`
367 #[cfg(feature = "debug_refcell")]
368 location: unwrap!(self.borrowed_at.get()),
369 }),
370 }
371 }
372
373 /// Mutably borrows the wrapped value.
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 /// # Panics
380 ///
381 /// Panics if the value is currently borrowed. For a non-panicking variant, use
382 /// [`try_borrow_mut`](#method.try_borrow_mut).
383 ///
384 /// # Examples
385 ///
386 /// ```
387 /// use std::cell::RefCell;
388 ///
389 /// let c = RefCell::new("hello".to_owned());
390 ///
391 /// *c.borrow_mut() = "bonjour".to_owned();
392 ///
393 /// assert_eq!(&*c.borrow(), "bonjour");
394 /// ```
395 ///
396 /// An example of panic:
397 ///
398 /// ```should_panic
399 /// use std::cell::RefCell;
400 ///
401 /// let c = RefCell::new(5);
402 /// let m = c.borrow();
403 ///
404 /// let b = c.borrow_mut(); // this causes a panic
405 /// ```
406 #[inline]
407 #[track_caller]
408 pub fn borrow_mut(&self) -> RefMut<'_, T> {
409 match self.try_borrow_mut() {
410 Ok(b) => b,
411 Err(err) => panic_already_borrowed(err),
412 }
413 }
414
415 /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
416 ///
417 /// The borrow lasts until the returned `RefMut` or all `RefMut`s derived
418 /// from it exit scope. The value cannot be borrowed while this borrow is
419 /// active.
420 ///
421 /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
422 ///
423 /// # Examples
424 ///
425 /// ```
426 /// use std::cell::RefCell;
427 ///
428 /// let c = RefCell::new(5);
429 ///
430 /// {
431 /// let m = c.borrow();
432 /// assert!(c.try_borrow_mut().is_err());
433 /// }
434 ///
435 /// assert!(c.try_borrow_mut().is_ok());
436 /// ```
437 #[inline]
438 pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
439 match BorrowRefMut::new(&self.borrow) {
440 Some(b) => {
441 #[cfg(feature = "debug_refcell")]
442 {
443 self.borrowed_at.set(Some(crate::panic::Location::caller()));
444 }
445
446 // SAFETY: `BorrowRefMut` guarantees unique access.
447 let value = unsafe { NonNull::new_unchecked(self.value.get()) };
448 Ok(RefMut {
449 value,
450 borrow: b,
451 marker: PhantomData,
452 })
453 }
454 None => Err(BorrowMutError {
455 // If a borrow occurred, then we must already have an outstanding borrow,
456 // so `borrowed_at` will be `Some`
457 #[cfg(feature = "debug_refcell")]
458 location: unwrap!(self.borrowed_at.get()),
459 }),
460 }
461 }
462
463 /// Returns a raw pointer to the underlying data in this cell.
464 ///
465 /// # Examples
466 ///
467 /// ```
468 /// use std::cell::RefCell;
469 ///
470 /// let c = RefCell::new(5);
471 ///
472 /// let ptr = c.as_ptr();
473 /// ```
474 #[inline]
475 //#[rustc_never_returns_null_ptr]
476 pub fn as_ptr(&self) -> *mut T {
477 self.value.get()
478 }
479
480 /// Returns a mutable reference to the underlying data.
481 ///
482 /// Since this method borrows `RefCell` mutably, it is statically guaranteed
483 /// that no borrows to the underlying data exist. The dynamic checks inherent
484 /// in [`borrow_mut`] and most other methods of `RefCell` are therefore
485 /// unnecessary.
486 ///
487 /// This method can only be called if `RefCell` can be mutably borrowed,
488 /// which in general is only the case directly after the `RefCell` has
489 /// been created. In these situations, skipping the aforementioned dynamic
490 /// borrowing checks may yield better ergonomics and runtime-performance.
491 ///
492 /// In most situations where `RefCell` is used, it can't be borrowed mutably.
493 /// Use [`borrow_mut`] to get mutable access to the underlying data then.
494 ///
495 /// [`borrow_mut`]: RefCell::borrow_mut()
496 ///
497 /// # Examples
498 ///
499 /// ```
500 /// use std::cell::RefCell;
501 ///
502 /// let mut c = RefCell::new(5);
503 /// *c.get_mut() += 1;
504 ///
505 /// assert_eq!(c, RefCell::new(6));
506 /// ```
507 #[inline]
508 pub fn get_mut(&mut self) -> &mut T {
509 self.value.get_mut()
510 }
511
512 /// Immutably borrows the wrapped value, returning an error if the value is
513 /// currently mutably borrowed.
514 ///
515 /// # Safety
516 ///
517 /// Unlike `RefCell::borrow`, this method is unsafe because it does not
518 /// return a `Ref`, thus leaving the borrow flag untouched. Mutably
519 /// borrowing the `RefCell` while the reference returned by this method
520 /// is alive is undefined behaviour.
521 ///
522 /// # Examples
523 ///
524 /// ```
525 /// use std::cell::RefCell;
526 ///
527 /// let c = RefCell::new(5);
528 ///
529 /// {
530 /// let m = c.borrow_mut();
531 /// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
532 /// }
533 ///
534 /// {
535 /// let m = c.borrow();
536 /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
537 /// }
538 /// ```
539 #[inline]
540 pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
541 if !is_writing(self.borrow.get()) {
542 // SAFETY: We check that nobody is actively writing now, but it is
543 // the caller's responsibility to ensure that nobody writes until
544 // the returned reference is no longer in use.
545 // Also, `self.value.get()` refers to the value owned by `self`
546 // and is thus guaranteed to be valid for the lifetime of `self`.
547 Ok(unsafe { &*self.value.get() })
548 } else {
549 Err(BorrowError {
550 // If a borrow occurred, then we must already have an outstanding borrow,
551 // so `borrowed_at` will be `Some`
552 #[cfg(feature = "debug_refcell")]
553 location: unwrap!(self.borrowed_at.get()),
554 })
555 }
556 }
557}
558
559impl<T: Default> RefCell<T> {
560 /// Takes the wrapped value, leaving `Default::default()` in its place.
561 ///
562 /// # Panics
563 ///
564 /// Panics if the value is currently borrowed.
565 ///
566 /// # Examples
567 ///
568 /// ```
569 /// use std::cell::RefCell;
570 ///
571 /// let c = RefCell::new(5);
572 /// let five = c.take();
573 ///
574 /// assert_eq!(five, 5);
575 /// assert_eq!(c.into_inner(), 0);
576 /// ```
577 pub fn take(&self) -> T {
578 self.replace(Default::default())
579 }
580}
581
582unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {}
583
584impl<T: Clone> Clone for RefCell<T> {
585 /// # Panics
586 ///
587 /// Panics if the value is currently mutably borrowed.
588 #[inline]
589 #[track_caller]
590 fn clone(&self) -> RefCell<T> {
591 RefCell::new(self.borrow().clone())
592 }
593
594 /// # Panics
595 ///
596 /// Panics if `other` is currently mutably borrowed.
597 #[inline]
598 #[track_caller]
599 fn clone_from(&mut self, other: &Self) {
600 self.get_mut().clone_from(&other.borrow())
601 }
602}
603
604impl<T: Default> Default for RefCell<T> {
605 /// Creates a `RefCell<T>`, with the `Default` value for T.
606 #[inline]
607 fn default() -> RefCell<T> {
608 RefCell::new(Default::default())
609 }
610}
611
612impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
613 /// # Panics
614 ///
615 /// Panics if the value in either `RefCell` is currently mutably borrowed.
616 #[inline]
617 fn eq(&self, other: &RefCell<T>) -> bool {
618 *self.borrow() == *other.borrow()
619 }
620}
621
622impl<T: ?Sized + Eq> Eq for RefCell<T> {}
623
624impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
625 /// # Panics
626 ///
627 /// Panics if the value in either `RefCell` is currently mutably borrowed.
628 #[inline]
629 fn partial_cmp(&self, other: &RefCell<T>) -> Option<Ordering> {
630 self.borrow().partial_cmp(&*other.borrow())
631 }
632
633 /// # Panics
634 ///
635 /// Panics if the value in either `RefCell` is currently mutably borrowed.
636 #[inline]
637 fn lt(&self, other: &RefCell<T>) -> bool {
638 *self.borrow() < *other.borrow()
639 }
640
641 /// # Panics
642 ///
643 /// Panics if the value in either `RefCell` is currently mutably borrowed.
644 #[inline]
645 fn le(&self, other: &RefCell<T>) -> bool {
646 *self.borrow() <= *other.borrow()
647 }
648
649 /// # Panics
650 ///
651 /// Panics if the value in either `RefCell` is currently mutably borrowed.
652 #[inline]
653 fn gt(&self, other: &RefCell<T>) -> bool {
654 *self.borrow() > *other.borrow()
655 }
656
657 /// # Panics
658 ///
659 /// Panics if the value in either `RefCell` is currently mutably borrowed.
660 #[inline]
661 fn ge(&self, other: &RefCell<T>) -> bool {
662 *self.borrow() >= *other.borrow()
663 }
664}
665
666impl<T: ?Sized + Ord> Ord for RefCell<T> {
667 /// # Panics
668 ///
669 /// Panics if the value in either `RefCell` is currently mutably borrowed.
670 #[inline]
671 fn cmp(&self, other: &RefCell<T>) -> Ordering {
672 self.borrow().cmp(&*other.borrow())
673 }
674}
675
676// NOTE: `core::cell::RefCell` defines `impl<T> From<T> for RefCell<T>`, but we
677// deliberately do NOT mirror it here. Because this `RefCell` is a crate-local
678// type (a copy of `core`'s, plus our `init` support), such a blanket `From<T>`
679// impl is subject to coherence checks against every *visible* impl in our
680// dependency graph - and `time` >= 0.3.48 has an
681// `impl From<HourBase> for <HourBase as ModifierValue>::Type` whose
682// associated-type projection the compiler cannot prove disjoint from
683// `RefCell<_>`, yielding a spurious `E0119`. `core`'s own impl is immune (the
684// orphan rule seals it and `time` is not in `core`'s graph). The impl is unused
685// anyway, so we simply omit it. See the `time` 0.3.48 coherence regression.
686
687struct BorrowRef<'b> {
688 borrow: &'b Cell<BorrowFlag>,
689}
690
691impl<'b> BorrowRef<'b> {
692 #[inline]
693 fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
694 let b = borrow.get().wrapping_add(1);
695 if !is_reading(b) {
696 // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
697 // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read borrow
698 // due to Rust's reference aliasing rules
699 // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed
700 // into isize::MIN (the max amount of writing borrows) so we can't allow
701 // an additional read borrow because isize can't represent so many read borrows
702 // (this can only happen if you mem::forget more than a small constant amount of
703 // `Ref`s, which is not good practice)
704 None
705 } else {
706 // Incrementing borrow can result in a reading value (> 0) in these cases:
707 // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
708 // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
709 // is large enough to represent having one more read borrow
710 borrow.set(b);
711 Some(BorrowRef { borrow })
712 }
713 }
714}
715
716impl Drop for BorrowRef<'_> {
717 #[inline]
718 fn drop(&mut self) {
719 let borrow = self.borrow.get();
720 debug_assert!(is_reading(borrow));
721 self.borrow.set(borrow - 1);
722 }
723}
724
725impl Clone for BorrowRef<'_> {
726 #[inline]
727 fn clone(&self) -> Self {
728 // Since this Ref exists, we know the borrow flag
729 // is a reading borrow.
730 let borrow = self.borrow.get();
731 debug_assert!(is_reading(borrow));
732 // Prevent the borrow counter from overflowing into
733 // a writing borrow.
734 assert!(borrow != BorrowFlag::MAX);
735 self.borrow.set(borrow + 1);
736 BorrowRef {
737 borrow: self.borrow,
738 }
739 }
740}
741
742/// Wraps a borrowed reference to a value in a `RefCell` box.
743/// A wrapper type for an immutably borrowed value from a `RefCell<T>`.
744///
745/// See the [module-level documentation](self) for more.
746// #[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"]
747// #[rustc_diagnostic_item = "RefCellRef"]
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 borrow: BorrowRef<'b>,
754}
755
756impl<T: ?Sized> Deref for Ref<'_, T> {
757 type Target = T;
758
759 #[inline]
760 fn deref(&self) -> &T {
761 // SAFETY: the value is accessible as long as we hold our borrow.
762 unsafe { self.value.as_ref() }
763 }
764}
765
766impl<'b, T: ?Sized> Ref<'b, T> {
767 /// Copies a `Ref`.
768 ///
769 /// The `RefCell` is already immutably borrowed, so this cannot fail.
770 ///
771 /// This is an associated function that needs to be used as
772 /// `Ref::clone(...)`. A `Clone` implementation or a method would interfere
773 /// with the widespread use of `r.borrow().clone()` to clone the contents of
774 /// a `RefCell`.
775 #[must_use]
776 #[inline]
777 pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
778 Ref {
779 value: orig.value,
780 borrow: orig.borrow.clone(),
781 }
782 }
783
784 /// Makes a new `Ref` for a component of the borrowed data.
785 ///
786 /// The `RefCell` is already immutably borrowed, so this cannot fail.
787 ///
788 /// This is an associated function that needs to be used as `Ref::map(...)`.
789 /// A method would interfere with methods of the same name on the contents
790 /// of a `RefCell` used through `Deref`.
791 ///
792 /// # Examples
793 ///
794 /// ```
795 /// use std::cell::{RefCell, Ref};
796 ///
797 /// let c = RefCell::new((5, 'b'));
798 /// let b1: Ref<'_, (u32, char)> = c.borrow();
799 /// let b2: Ref<'_, u32> = Ref::map(b1, |t| &t.0);
800 /// assert_eq!(*b2, 5)
801 /// ```
802 #[inline]
803 pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
804 where
805 F: FnOnce(&T) -> &U,
806 {
807 Ref {
808 value: NonNull::from(f(&*orig)),
809 borrow: orig.borrow,
810 }
811 }
812
813 /// Makes a new `Ref` for an optional component of the borrowed data. The
814 /// original guard is returned as an `Err(..)` if the closure returns
815 /// `None`.
816 ///
817 /// The `RefCell` is already immutably borrowed, so this cannot fail.
818 ///
819 /// This is an associated function that needs to be used as
820 /// `Ref::filter_map(...)`. A method would interfere with methods of the same
821 /// name on the contents of a `RefCell` used through `Deref`.
822 ///
823 /// # Examples
824 ///
825 /// ```
826 /// use std::cell::{RefCell, Ref};
827 ///
828 /// let c = RefCell::new(vec![1, 2, 3]);
829 /// let b1: Ref<'_, Vec<u32>> = c.borrow();
830 /// let b2: Result<Ref<'_, u32>, _> = Ref::filter_map(b1, |v| v.get(1));
831 /// assert_eq!(*b2.unwrap(), 2);
832 /// ```
833 #[inline]
834 pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Result<Ref<'b, U>, Self>
835 where
836 F: FnOnce(&T) -> Option<&U>,
837 {
838 match f(&*orig) {
839 Some(value) => Ok(Ref {
840 value: NonNull::from(value),
841 borrow: orig.borrow,
842 }),
843 None => Err(orig),
844 }
845 }
846
847 /// Splits a `Ref` into multiple `Ref`s for different components of the
848 /// borrowed data.
849 ///
850 /// The `RefCell` is already immutably borrowed, so this cannot fail.
851 ///
852 /// This is an associated function that needs to be used as
853 /// `Ref::map_split(...)`. A method would interfere with methods of the same
854 /// name on the contents of a `RefCell` used through `Deref`.
855 ///
856 /// # Examples
857 ///
858 /// ```
859 /// use std::cell::{Ref, RefCell};
860 ///
861 /// let cell = RefCell::new([1, 2, 3, 4]);
862 /// let borrow = cell.borrow();
863 /// let (begin, end) = Ref::map_split(borrow, |slice| slice.split_at(2));
864 /// assert_eq!(*begin, [1, 2]);
865 /// assert_eq!(*end, [3, 4]);
866 /// ```
867 #[inline]
868 pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>, Ref<'b, V>)
869 where
870 F: FnOnce(&T) -> (&U, &V),
871 {
872 let (a, b) = f(&*orig);
873 let borrow = orig.borrow.clone();
874 (
875 Ref {
876 value: NonNull::from(a),
877 borrow,
878 },
879 Ref {
880 value: NonNull::from(b),
881 borrow: orig.borrow,
882 },
883 )
884 }
885}
886
887impl<T: ?Sized + fmt::Display> fmt::Display for Ref<'_, T> {
888 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
889 (**self).fmt(f)
890 }
891}
892
893impl<'b, T: ?Sized> RefMut<'b, T> {
894 /// Makes a new `RefMut` for a component of the borrowed data, e.g., an enum
895 /// variant.
896 ///
897 /// The `RefCell` is already mutably borrowed, so this cannot fail.
898 ///
899 /// This is an associated function that needs to be used as
900 /// `RefMut::map(...)`. A method would interfere with methods of the same
901 /// name on the contents of a `RefCell` used through `Deref`.
902 ///
903 /// # Examples
904 ///
905 /// ```
906 /// use std::cell::{RefCell, RefMut};
907 ///
908 /// let c = RefCell::new((5, 'b'));
909 /// {
910 /// let b1: RefMut<'_, (u32, char)> = c.borrow_mut();
911 /// let mut b2: RefMut<'_, u32> = RefMut::map(b1, |t| &mut t.0);
912 /// assert_eq!(*b2, 5);
913 /// *b2 = 42;
914 /// }
915 /// assert_eq!(*c.borrow(), (42, 'b'));
916 /// ```
917 #[inline]
918 pub fn map<U: ?Sized, F>(mut orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
919 where
920 F: FnOnce(&mut T) -> &mut U,
921 {
922 let value = NonNull::from(f(&mut *orig));
923 RefMut {
924 value,
925 borrow: orig.borrow,
926 marker: PhantomData,
927 }
928 }
929
930 /// Makes a new `RefMut` for an optional component of the borrowed data. The
931 /// original guard is returned as an `Err(..)` if the closure returns
932 /// `None`.
933 ///
934 /// The `RefCell` is already mutably borrowed, so this cannot fail.
935 ///
936 /// This is an associated function that needs to be used as
937 /// `RefMut::filter_map(...)`. A method would interfere with methods of the
938 /// same name on the contents of a `RefCell` used through `Deref`.
939 ///
940 /// # Examples
941 ///
942 /// ```
943 /// use std::cell::{RefCell, RefMut};
944 ///
945 /// let c = RefCell::new(vec![1, 2, 3]);
946 ///
947 /// {
948 /// let b1: RefMut<'_, Vec<u32>> = c.borrow_mut();
949 /// let mut b2: Result<RefMut<'_, u32>, _> = RefMut::filter_map(b1, |v| v.get_mut(1));
950 ///
951 /// if let Ok(mut b2) = b2 {
952 /// *b2 += 2;
953 /// }
954 /// }
955 ///
956 /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
957 /// ```
958 #[inline]
959 pub fn filter_map<U: ?Sized, F>(mut orig: RefMut<'b, T>, f: F) -> Result<RefMut<'b, U>, Self>
960 where
961 F: FnOnce(&mut T) -> Option<&mut U>,
962 {
963 // SAFETY: function holds onto an exclusive reference for the duration
964 // of its call through `orig`, and the pointer is only de-referenced
965 // inside of the function call never allowing the exclusive reference to
966 // escape.
967 match f(&mut *orig) {
968 Some(value) => Ok(RefMut {
969 value: NonNull::from(value),
970 borrow: orig.borrow,
971 marker: PhantomData,
972 }),
973 None => Err(orig),
974 }
975 }
976
977 /// Splits a `RefMut` into multiple `RefMut`s for different components of the
978 /// borrowed data.
979 ///
980 /// The underlying `RefCell` will remain mutably borrowed until both
981 /// returned `RefMut`s go out of scope.
982 ///
983 /// The `RefCell` is already mutably borrowed, so this cannot fail.
984 ///
985 /// This is an associated function that needs to be used as
986 /// `RefMut::map_split(...)`. A method would interfere with methods of the
987 /// same name on the contents of a `RefCell` used through `Deref`.
988 ///
989 /// # Examples
990 ///
991 /// ```
992 /// use std::cell::{RefCell, RefMut};
993 ///
994 /// let cell = RefCell::new([1, 2, 3, 4]);
995 /// let borrow = cell.borrow_mut();
996 /// let (mut begin, mut end) = RefMut::map_split(borrow, |slice| slice.split_at_mut(2));
997 /// assert_eq!(*begin, [1, 2]);
998 /// assert_eq!(*end, [3, 4]);
999 /// begin.copy_from_slice(&[4, 3]);
1000 /// end.copy_from_slice(&[2, 1]);
1001 /// ```
1002 #[inline]
1003 pub fn map_split<U: ?Sized, V: ?Sized, F>(
1004 mut orig: RefMut<'b, T>,
1005 f: F,
1006 ) -> (RefMut<'b, U>, RefMut<'b, V>)
1007 where
1008 F: FnOnce(&mut T) -> (&mut U, &mut V),
1009 {
1010 let borrow = orig.borrow.clone();
1011 let (a, b) = f(&mut *orig);
1012 (
1013 RefMut {
1014 value: NonNull::from(a),
1015 borrow,
1016 marker: PhantomData,
1017 },
1018 RefMut {
1019 value: NonNull::from(b),
1020 borrow: orig.borrow,
1021 marker: PhantomData,
1022 },
1023 )
1024 }
1025}
1026
1027struct BorrowRefMut<'b> {
1028 borrow: &'b Cell<BorrowFlag>,
1029}
1030
1031impl Drop for BorrowRefMut<'_> {
1032 #[inline]
1033 fn drop(&mut self) {
1034 let borrow = self.borrow.get();
1035 debug_assert!(is_writing(borrow));
1036 self.borrow.set(borrow + 1);
1037 }
1038}
1039
1040impl<'b> BorrowRefMut<'b> {
1041 #[inline]
1042 fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
1043 // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
1044 // mutable reference, and so there must currently be no existing
1045 // references. Thus, while clone increments the mutable refcount, here
1046 // we explicitly only allow going from UNUSED to UNUSED - 1.
1047 match borrow.get() {
1048 UNUSED => {
1049 borrow.set(UNUSED - 1);
1050 Some(BorrowRefMut { borrow })
1051 }
1052 _ => None,
1053 }
1054 }
1055
1056 // Clones a `BorrowRefMut`.
1057 //
1058 // This is only valid if each `BorrowRefMut` is used to track a mutable
1059 // reference to a distinct, nonoverlapping range of the original object.
1060 // This isn't in a Clone impl so that code doesn't call this implicitly.
1061 #[inline]
1062 fn clone(&self) -> BorrowRefMut<'b> {
1063 let borrow = self.borrow.get();
1064 debug_assert!(is_writing(borrow));
1065 // Prevent the borrow counter from underflowing.
1066 assert!(borrow != BorrowFlag::MIN);
1067 self.borrow.set(borrow - 1);
1068 BorrowRefMut {
1069 borrow: self.borrow,
1070 }
1071 }
1072}
1073
1074/// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
1075///
1076/// See the [module-level documentation](self) for more.
1077// #[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"]
1078// #[rustc_diagnostic_item = "RefCellRefMut"]
1079pub struct RefMut<'b, T: ?Sized + 'b> {
1080 // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a
1081 // `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops.
1082 value: NonNull<T>,
1083 borrow: BorrowRefMut<'b>,
1084 // `NonNull` is covariant over `T`, so we need to reintroduce invariance.
1085 marker: PhantomData<&'b mut T>,
1086}
1087
1088impl<T: ?Sized> Deref for RefMut<'_, T> {
1089 type Target = T;
1090
1091 #[inline]
1092 fn deref(&self) -> &T {
1093 // SAFETY: the value is accessible as long as we hold our borrow.
1094 unsafe { self.value.as_ref() }
1095 }
1096}
1097
1098impl<T: ?Sized> DerefMut for RefMut<'_, T> {
1099 #[inline]
1100 fn deref_mut(&mut self) -> &mut T {
1101 // SAFETY: the value is accessible as long as we hold our borrow.
1102 unsafe { self.value.as_mut() }
1103 }
1104}
1105
1106impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
1107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1108 (**self).fmt(f)
1109 }
1110}