1#![deny(missing_docs)]
31
32pub mod error {
34 #[cfg(debug_assertions)]
35 fn locations_display(locations: &[super::Location]) -> String {
36 locations
37 .iter()
38 .map(|location| format!(" ---------------\n {location}"))
39 .collect::<Vec<_>>()
40 .join("\n")
41 }
42 #[non_exhaustive]
44 #[derive(Debug)]
45 pub struct BorrowError {
46 #[cfg(debug_assertions)]
48 pub attempted_at: super::Location,
49 #[cfg(debug_assertions)]
51 pub already_borrowed_at: Vec<super::Location>,
52 }
53
54 impl std::error::Error for BorrowError {}
55
56 impl std::fmt::Display for BorrowError {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 #[cfg(debug_assertions)]
59 {
60 write!(
61 f,
62 "Value is already borrowed mutably, current active borrows: \n{}\n\n",
63 locations_display(&self.already_borrowed_at)
64 )
65 }
66 #[cfg(not(debug_assertions))]
67 {
68 write!(f, "Value is already borrowed mutably")
69 }
70 }
71 }
72
73 impl std::error::Error for BorrowMutError {}
74
75 #[derive(Debug)]
77 #[non_exhaustive]
78 pub struct BorrowMutError {
79 #[cfg(debug_assertions)]
81 pub attempted_at: super::Location,
82 #[cfg(debug_assertions)]
84 pub already_borrowed_at: Vec<super::Location>,
85 }
86
87 impl std::fmt::Display for BorrowMutError {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 #[cfg(debug_assertions)]
90 {
91 write!(
92 f,
93 "Value is already borrowed, current active borrows:\n{}\n\n",
94 locations_display(&self.already_borrowed_at)
95 )
96 }
97 #[cfg(not(debug_assertions))]
98 {
99 write!(f, "Value is already borrowed")
100 }
101 }
102 }
103}
104
105#[cfg(debug_assertions)]
106use std::cell::RefCell as StdRefCell;
107use std::cell::{Cell, UnsafeCell};
108use std::ops::{Deref, DerefMut};
109
110pub struct RefCell<T: ?Sized> {
112 borrow: BorrowFlag,
113 value: UnsafeCell<T>,
114}
115
116#[cfg(not(debug_assertions))]
117type Location = ();
118
119#[cfg(debug_assertions)]
120type Location = &'static std::panic::Location<'static>;
121
122#[derive(Copy, Clone, PartialEq, Eq, Debug)]
124pub enum BorrowState {
125 Reading,
127 Writing,
129 Unused,
131}
132
133struct BorrowFlag {
136 flag: Cell<usize>,
137
138 #[cfg(debug_assertions)]
139 locations: StdRefCell<Vec<Location>>,
140}
141
142const UNUSED: usize = 0;
143const WRITING: usize = !0;
144
145impl<T> RefCell<T> {
146 pub fn new(value: T) -> RefCell<T> {
148 RefCell {
149 borrow: BorrowFlag::new(),
150 value: UnsafeCell::new(value),
151 }
152 }
153
154 #[cfg_attr(debug_assertions, track_caller)]
156 pub fn into_inner(self) -> T {
157 debug_assert!(self.borrow.flag.get() == UNUSED);
158 self.value.into_inner()
159 }
160}
161
162impl<T: ?Sized> RefCell<T> {
163 #[cfg_attr(debug_assertions, inline(never))]
172 #[cfg_attr(debug_assertions, track_caller)]
173 pub fn borrow(&self) -> Ref<'_, T> {
174 match self.try_borrow() {
175 Ok(value) => value,
176 Err(message) => panic!(
177 "Borrowing {} immutably failed: {}",
178 std::any::type_name::<Self>(),
179 message
180 ),
181 }
182 }
183 #[cfg_attr(debug_assertions, inline(never))]
192 #[cfg_attr(debug_assertions, track_caller)]
193 pub fn try_borrow(&self) -> Result<Ref<'_, T>, crate::error::BorrowError> {
194 match BorrowRef::new(&self.borrow) {
195 Some(b) => Ok(Ref {
196 _value: unsafe { &*self.value.get() },
197 _borrow: b,
198 }),
199 None => {
200 #[cfg(debug_assertions)]
201 {
202 Err(crate::error::BorrowError {
203 attempted_at: get_caller(),
204 already_borrowed_at: self.borrow.locations.borrow().clone(),
205 })
206 }
207 #[cfg(not(debug_assertions))]
208 {
209 Err(crate::error::BorrowError {})
210 }
211 }
212 }
213 }
214
215 #[cfg_attr(debug_assertions, inline(never))]
224 #[cfg_attr(debug_assertions, track_caller)]
225 pub fn borrow_mut(&self) -> RefMut<'_, T> {
226 match self.try_borrow_mut() {
227 Ok(value) => value,
228 Err(message) => panic!(
229 "Borrowing {} mutably failed: {}",
230 std::any::type_name::<Self>(),
231 message
232 ),
233 }
234 }
235
236 #[cfg_attr(debug_assertions, inline(never))]
242 #[cfg_attr(debug_assertions, track_caller)]
243 pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, error::BorrowMutError> {
244 match BorrowRefMut::new(&self.borrow) {
245 Some(b) => Ok(RefMut {
246 _value: unsafe { &mut *self.value.get() },
247 _borrow: b,
248 }),
249 None => {
250 #[cfg(debug_assertions)]
251 {
252 Err(error::BorrowMutError {
253 attempted_at: get_caller(),
254 already_borrowed_at: self.borrow.locations.borrow().clone(),
255 })
256 }
257 #[cfg(not(debug_assertions))]
258 {
259 Err(error::BorrowMutError {})
260 }
261 }
262 }
263 }
264}
265
266#[cfg(not(debug_assertions))]
267impl BorrowFlag {
268 #[inline]
269 fn new() -> BorrowFlag {
270 BorrowFlag {
271 flag: Cell::new(UNUSED),
272 }
273 }
274
275 #[inline]
276 fn push(&self, _caller: Location) {}
277
278 #[inline]
279 fn pop(&self) {}
280}
281
282#[cfg(debug_assertions)]
283impl BorrowFlag {
284 fn new() -> BorrowFlag {
285 BorrowFlag {
286 flag: Cell::new(UNUSED),
287 locations: StdRefCell::new(Vec::new()),
288 }
289 }
290
291 fn push(&self, caller: Location) {
292 self.locations.borrow_mut().push(caller);
293 }
294
295 fn pop(&self) {
296 self.locations.borrow_mut().pop();
297 }
298}
299
300#[cfg(not(debug_assertions))]
301#[inline]
302fn get_caller() -> Location {}
303
304#[cfg(debug_assertions)]
305#[inline(never)]
306#[track_caller]
307fn get_caller() -> Location {
308 std::panic::Location::caller()
309}
310
311unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {}
312
313impl<T: Clone> Clone for RefCell<T> {
314 #[inline]
315 fn clone(&self) -> RefCell<T> {
316 RefCell::new(self.borrow().clone())
317 }
318}
319
320impl<T: Default> Default for RefCell<T> {
321 #[inline]
322 fn default() -> RefCell<T> {
323 RefCell::new(Default::default())
324 }
325}
326
327impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
328 #[inline]
329 fn eq(&self, other: &RefCell<T>) -> bool {
330 *self.borrow() == *other.borrow()
331 }
332}
333
334impl<T: ?Sized + Eq> Eq for RefCell<T> {}
335
336struct BorrowRef<'b> {
337 borrow: &'b BorrowFlag,
338}
339
340impl<'b> BorrowRef<'b> {
341 #[cfg_attr(not(debug_assertions), inline)]
342 #[cfg_attr(debug_assertions, inline(never))]
343 #[cfg_attr(debug_assertions, track_caller)]
344 fn new(borrow: &'b BorrowFlag) -> Option<BorrowRef<'b>> {
345 let flag = borrow.flag.get();
346 if flag == WRITING {
347 return None;
348 }
349 borrow.flag.set(flag + 1);
350 borrow.push(get_caller());
351 Some(BorrowRef { borrow })
352 }
353}
354
355impl<'b> Drop for BorrowRef<'b> {
356 #[inline]
357 fn drop(&mut self) {
358 let flag = self.borrow.flag.get();
359 debug_assert!(flag != WRITING && flag != UNUSED);
360 self.borrow.flag.set(flag - 1);
361 self.borrow.pop();
362 }
363}
364
365pub struct Ref<'b, T: ?Sized + 'b> {
371 _value: &'b T,
374 _borrow: BorrowRef<'b>,
375}
376
377impl<'b, T: ?Sized + 'b> Ref<'b, T> {
378 #[inline]
397 pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
398 where
399 F: FnOnce(&T) -> &U,
400 {
401 Ref {
402 _value: f(&*orig._value),
403 _borrow: orig._borrow,
404 }
405 }
406}
407
408impl<'b, T: ?Sized> Deref for Ref<'b, T> {
409 type Target = T;
410 fn deref(&self) -> &T {
411 self._value
412 }
413}
414
415struct BorrowRefMut<'b> {
416 borrow: &'b BorrowFlag,
417}
418
419impl<'b> BorrowRefMut<'b> {
420 #[cfg_attr(not(debug_assertions), inline)]
421 #[cfg_attr(debug_assertions, inline(never))]
422 #[cfg_attr(debug_assertions, track_caller)]
423 fn new(borrow: &'b BorrowFlag) -> Option<BorrowRefMut<'b>> {
424 if borrow.flag.get() != UNUSED {
425 return None;
426 }
427 borrow.flag.set(WRITING);
428 borrow.push(get_caller());
429 Some(BorrowRefMut { borrow })
430 }
431}
432
433impl<'b> Drop for BorrowRefMut<'b> {
434 #[inline]
435 fn drop(&mut self) {
436 debug_assert!(self.borrow.flag.get() == WRITING);
437 self.borrow.flag.set(UNUSED);
438 self.borrow.pop();
439 }
440}
441
442pub struct RefMut<'b, T: ?Sized + 'b> {
444 _value: &'b mut T,
447 _borrow: BorrowRefMut<'b>,
448}
449
450impl<'b, T: ?Sized + 'b> RefMut<'b, T> {
451 pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
475 where
476 F: FnOnce(&mut T) -> &mut U,
477 {
478 RefMut {
479 _value: f(&mut *orig._value),
480 _borrow: orig._borrow,
481 }
482 }
483}
484
485impl<'b, T: ?Sized> Deref for RefMut<'b, T> {
486 type Target = T;
487 fn deref(&self) -> &T {
488 self._value
489 }
490}
491
492impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
493 fn deref_mut(&mut self) -> &mut T {
494 self._value
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::RefCell;
501
502 #[test]
503 fn ok_borrows() {
504 let a = RefCell::new(2);
505 let b = a.borrow();
506 let c = a.borrow();
507 assert_eq!(*b, 2);
508 assert_eq!(*c, 2);
509 drop((b, c));
510
511 let mut b = a.borrow_mut();
512 assert_eq!(*b, 2);
513 *b = 4;
514 drop(b);
515
516 assert_eq!(*a.borrow(), 4);
517 }
518
519 #[test]
520 fn ok_borrows_map() {
521 let a = RefCell::new((0, 1));
522 let b = a.borrow();
523 let c = super::Ref::map(b, |v| &v.0);
524 assert_eq!(*c, 0);
525 assert!(a.try_borrow().is_ok());
526 assert!(a.try_borrow_mut().is_err());
527 drop(c);
528 assert!(a.try_borrow().is_ok());
529 assert!(a.try_borrow_mut().is_ok());
530
531 let mut b = a.borrow_mut();
532 assert_eq!(b.0, 0);
533 b.0 = 999;
534 drop(b);
535
536 assert_eq!(a.borrow().0, 999);
537 }
538
539 #[test]
540 fn ok_borrow_mut_map() {
541 let a = RefCell::new((0, 1));
542 let b = a.borrow_mut();
543 let mut c = super::RefMut::map(b, |v| &mut v.0);
544 assert_eq!(*c, 0);
545 *c = 999;
546 drop(c);
547 assert_eq!(a.try_borrow().unwrap().0, 999);
548 }
549
550 #[should_panic]
551 #[test]
552 fn bad_borrow_mut() {
553 let a = RefCell::new(2);
554 let _a = a.borrow();
555 a.borrow_mut();
556 }
557
558 #[should_panic]
559 #[test]
560 fn bad_borrow() {
561 let a = RefCell::new(2);
562 let _a = a.borrow_mut();
563 a.borrow();
564 }
565}