1extern crate backtrace;
6
7use backtrace::Backtrace;
8use std::cell::{
9 BorrowError, BorrowMutError, Ref as StdRef, RefCell as StdRefCell, RefMut as StdRefMut,
10};
11use std::fmt::{Debug, Display, Error, Formatter};
12use std::ops::{Deref, DerefMut};
13use std::{env, mem};
14
15#[derive(Debug)]
17pub struct RefCell<T: ?Sized> {
18 borrows: StdRefCell<BorrowData>,
19 inner: StdRefCell<T>,
20}
21
22#[derive(Debug)]
23struct BorrowData {
24 next_id: usize,
25 borrows: Vec<BorrowRecord>,
26}
27
28#[derive(Debug)]
29struct BorrowRecord {
30 id: usize,
31 backtrace: Backtrace,
32}
33
34impl BorrowData {
35 fn record(&mut self) -> usize {
36 let id = self.next_id();
37 self.borrows.push(BorrowRecord {
38 id: id,
39 backtrace: Backtrace::new(),
40 });
41 id
42 }
43
44 fn next_id(&mut self) -> usize {
45 let id = self.next_id;
46 self.next_id = id.wrapping_add(1);
47 id
48 }
49
50 fn remove_matching_record(&mut self, id: usize) {
51 let idx = self.borrows.iter().position(|record| record.id == id);
52 self.borrows.remove(idx.expect("missing borrow record"));
53 }
54}
55
56impl<T> RefCell<T> {
57 pub fn new(value: T) -> RefCell<T> {
59 RefCell {
60 inner: StdRefCell::new(value),
61 borrows: StdRefCell::new(BorrowData {
62 borrows: vec![],
63 next_id: 0,
64 }),
65 }
66 }
67
68 pub fn into_inner(self) -> T {
70 self.inner.into_inner()
71 }
72}
73
74pub struct Ref<'a, T: ?Sized + 'a> {
76 inner: StdRef<'a, T>,
77 data: RefBorrowData<'a>,
78}
79
80impl<'a, T: ?Sized> Ref<'a, T> {
81 pub fn clone(orig: &Ref<'a, T>) -> Ref<'a, T> {
84 let id = orig.data.cell.borrow_mut().record();
85 Ref {
86 inner: StdRef::clone(&orig.inner),
87 data: RefBorrowData {
88 cell: orig.data.cell,
89 id: id,
90 },
91 }
92 }
93
94 pub fn map<U: ?Sized, F>(orig: Ref<'a, T>, f: F) -> Ref<'a, U>
95 where
96 F: FnOnce(&T) -> &U,
97 {
98 Ref {
99 inner: StdRef::map(StdRef::clone(&orig.inner), f),
100 data: orig.data,
101 }
102 }
103
104 pub fn filter_map<U: ?Sized, F>(orig: Ref<'a, T>, f: F) -> Result<Ref<'a, U>, Self>
105 where
106 F: FnOnce(&T) -> Option<&U>,
107 {
108 match f(&orig).map(|new| new as *const U) {
109 Some(raw) => Ok(Ref::map(orig, |_| unsafe { &*raw })),
110 None => Err(orig),
111 }
112 }
113}
114
115impl<'a, T: ?Sized + Display> Display for Ref<'a, T> {
116 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
117 self.inner.fmt(f)
118 }
119}
120
121impl<'b, T: ?Sized + Debug> Debug for Ref<'b, T> {
122 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
123 self.inner.fmt(f)
124 }
125}
126
127impl<'a, T: ?Sized> Deref for Ref<'a, T> {
128 type Target = T;
129
130 fn deref(&self) -> &T {
131 &*self.inner
132 }
133}
134
135pub struct RefMut<'a, T: ?Sized + 'a> {
137 inner: StdRefMut<'a, T>,
138 data: RefBorrowData<'a>,
139}
140
141struct RefBorrowData<'a> {
142 cell: &'a StdRefCell<BorrowData>,
143 id: usize,
144}
145
146impl<'a> Drop for RefBorrowData<'a> {
147 fn drop(&mut self) {
148 self.cell.borrow_mut().remove_matching_record(self.id);
149 }
150}
151
152impl<'a, T: ?Sized> RefMut<'a, T> {
153 pub fn map<U: ?Sized, F>(orig: RefMut<'a, T>, f: F) -> RefMut<'a, U>
154 where
155 F: FnOnce(&mut T) -> &mut U,
156 {
157 let RefMut { inner, data } = orig;
158 RefMut {
159 inner: StdRefMut::map(inner, f),
160 data,
161 }
162 }
163
164 pub fn filter_map<U: ?Sized, F>(mut orig: RefMut<'a, T>, f: F) -> Result<RefMut<'a, U>, Self>
165 where
166 F: FnOnce(&mut T) -> Option<&mut U>,
167 {
168 match f(&mut orig).map(|new| new as *mut U) {
169 Some(raw) => Ok(RefMut::map(orig, |_| unsafe { &mut *raw })),
170 None => Err(orig),
171 }
172 }
173}
174
175impl<'a, T: ?Sized> Deref for RefMut<'a, T> {
176 type Target = T;
177
178 fn deref(&self) -> &T {
179 &*self.inner
180 }
181}
182
183impl<'a, T: ?Sized> DerefMut for RefMut<'a, T> {
184 fn deref_mut(&mut self) -> &mut T {
185 &mut *self.inner
186 }
187}
188
189impl<T: ?Sized> RefCell<T> {
190 pub fn borrow(&self) -> Ref<'_, T> {
193 if let Ok(r) = self.inner.try_borrow() {
194 let id = self.borrows.borrow_mut().record();
195 Ref {
196 inner: r,
197 data: RefBorrowData {
198 cell: &self.borrows,
199 id: id,
200 },
201 }
202 } else {
203 if let Ok(var) = env::var("RUST_BACKTRACE") {
204 if !var.is_empty() {
205 eprintln!("Outstanding borrow:");
206 print_filtered_backtrace(&self.borrows.borrow().borrows[0].backtrace);
207 }
208 }
209 panic!("RefCell is already mutably borrowed.");
210 }
211 }
212
213 pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
214 self.inner.try_borrow().map(|r| {
215 let id = self.borrows.borrow_mut().record();
216 Ref {
217 inner: r,
218 data: RefBorrowData {
219 cell: &self.borrows,
220 id: id,
221 },
222 }
223 })
224 }
225
226 pub fn borrow_mut(&self) -> RefMut<T> {
229 if let Ok(r) = self.inner.try_borrow_mut() {
230 let id = self.borrows.borrow_mut().record();
231 RefMut {
232 inner: r,
233 data: RefBorrowData {
234 cell: &self.borrows,
235 id: id,
236 },
237 }
238 } else {
239 if let Ok(var) = env::var("RUST_BACKTRACE") {
240 if !var.is_empty() {
241 eprintln!("Outstanding borrows:");
242 for borrow in &*self.borrows.borrow().borrows {
243 print_filtered_backtrace(&borrow.backtrace);
244 eprintln!("");
245 }
246 }
247 }
248 panic!("RefCell is already borrowed.");
249 }
250 }
251
252 pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
253 self.inner.try_borrow_mut().map(|r| {
254 let id = self.borrows.borrow_mut().record();
255 RefMut {
256 inner: r,
257 data: RefBorrowData {
258 cell: &self.borrows,
259 id: id,
260 },
261 }
262 })
263 }
264
265 pub fn as_ptr(&self) -> *mut T {
266 self.inner.as_ptr()
267 }
268
269 pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
270 self.inner.try_borrow_unguarded()
271 }
272}
273
274impl<T> RefCell<T> {
275 pub fn replace(&self, t: T) -> T {
277 mem::replace(&mut *self.borrow_mut(), t)
278 }
279
280 pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
282 let mut_borrow = &mut *self.borrow_mut();
283 let replacement = f(mut_borrow);
284 mem::replace(mut_borrow, replacement)
285 }
286}
287
288fn print_filtered_backtrace(backtrace: &Backtrace) {
290 let mut idx = 1;
291 for frame in backtrace.frames().iter() {
292 let symbol = frame.symbols().first();
293 let repr = match symbol {
294 None => "<no-info>".to_owned(),
295 Some(symbol) => {
296 let mut repr = if let Some(name) = symbol.name() {
297 if name.as_str().unwrap_or("").starts_with("backtrace::") {
298 continue;
299 }
300 name.as_str().unwrap_or("").to_owned()
301 } else {
302 "<unknown>".to_owned()
303 };
304 if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
305 repr.push_str(&format!(" at {:?}:{}", file, line));
306 }
307 repr
308 }
309 };
310 eprintln!("{:4}: {}", idx, repr);
311 idx += 1;
312 }
313}
314
315impl<T: Clone> Clone for RefCell<T> {
316 fn clone(&self) -> RefCell<T> {
317 RefCell::new(self.borrow().clone())
318 }
319}
320
321impl<T: Default> RefCell<T> {
322 pub fn take(&self) -> T {
324 self.replace(Default::default())
325 }
326}
327
328impl<T: Default> Default for RefCell<T> {
329 fn default() -> RefCell<T> {
330 RefCell::new(Default::default())
331 }
332}
333
334impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
335 fn eq(&self, other: &RefCell<T>) -> bool {
336 *self.borrow() == *other.borrow()
337 }
338}
339
340#[deprecated(since = "0.2.2", note = "Users should instead use Ref::filter_map")]
341pub fn ref_filter_map<T: ?Sized, U: ?Sized, F: FnOnce(&T) -> Option<&U>>(
342 orig: Ref<T>,
343 f: F,
344) -> Option<Ref<U>> {
345 f(&orig)
346 .map(|new| new as *const U)
347 .map(|raw| Ref::map(orig, |_| unsafe { &*raw }))
348}
349
350#[deprecated(since = "0.2.2", note = "Users should instead use RefMut::filter_map")]
351pub fn ref_mut_filter_map<T: ?Sized, U: ?Sized, F: FnOnce(&mut T) -> Option<&mut U>>(
352 mut orig: RefMut<T>,
353 f: F,
354) -> Option<RefMut<U>> {
355 f(&mut orig)
356 .map(|new| new as *mut U)
357 .map(|raw| RefMut::map(orig, |_| unsafe { &mut *raw }))
358}
359
360#[cfg(test)]
361mod tests {
362 use super::{Ref, RefCell};
363
364 #[test]
365 #[should_panic(expected = "RefCell is already borrowed")]
366 fn cannot_borrow_mutably() {
367 let c = RefCell::new(5);
368 let _b = c.borrow();
369 let _b2 = c.borrow_mut();
370 }
371
372 #[test]
373 #[should_panic(expected = "RefCell is already mutably borrowed")]
374 fn cannot_borrow_immutably() {
375 let c = RefCell::new(5);
376 let _b = c.borrow_mut();
377 let _b2 = c.borrow();
378 }
379
380 #[test]
381 #[should_panic(expected = "RefCell is already borrowed")]
382 fn cannot_double_borrow_mut() {
383 let c = RefCell::new(5);
384 let _b = c.borrow_mut();
385 let _b2 = c.borrow_mut();
386 }
387
388 #[inline(never)]
389 fn borrow_immutably<T>(cell: &RefCell<T>) -> Ref<T> {
390 cell.borrow()
391 }
392
393 #[test]
394 #[should_panic]
395 fn cannot_borrow_mutably_multi_borrow() {
396 let c = RefCell::new(5);
397 let _b = borrow_immutably(&c);
398 let _b2 = borrow_immutably(&c);
399 let _b2 = c.borrow_mut();
400 }
401
402 #[test]
403 #[should_panic]
404 fn clone_records_borrow() {
405 let c = RefCell::new(5);
406 let _b2 = {
407 let _b = borrow_immutably(&c);
408 Ref::clone(&_b)
409 };
410 let _b2 = c.borrow_mut();
411 }
412
413 #[test]
414 fn take_refcell_returns_correct_value() {
415 let c: RefCell<i32> = RefCell::new(5);
416 assert_eq!(5, c.take());
417 assert_eq!(i32::default(), *c.borrow());
418 }
419
420 #[test]
421 #[should_panic(expected = "RefCell is already borrowed")]
422 fn cannot_take_borrowed_refcell() {
423 let c = RefCell::new(5);
424 let _b = c.borrow();
425 c.take();
426 }
427
428 #[test]
429 #[should_panic(expected = "RefCell is already borrowed")]
430 fn cannot_take_mut_borrowed_refcell() {
431 let c = RefCell::new(5);
432 let _b = c.borrow_mut();
433 c.take();
434 }
435
436 #[test]
437 fn replace_refcell_properly_replaces_contents() {
438 let c = RefCell::new(5);
439 c.replace(12);
440 assert_eq!(12, *c.borrow());
441 }
442
443 #[test]
444 #[should_panic(expected = "RefCell is already borrowed")]
445 fn cannot_replace_borrowed_refcell() {
446 let c = RefCell::new(5);
447 let _b = c.borrow();
448 c.replace(12);
449 }
450
451 #[test]
452 #[should_panic(expected = "RefCell is already borrowed")]
453 fn cannot_replace_mut_borrowed_refcell() {
454 let c = RefCell::new(5);
455 let _b = c.borrow_mut();
456 c.replace(12);
457 }
458
459 #[test]
460 fn replace_with_refcell_properly_replaces_contents() {
461 let c = RefCell::new(5);
462 c.replace_with(|&mut old_value| old_value + 1);
463 assert_eq!(6, *c.borrow());
464 }
465
466 #[test]
467 #[should_panic(expected = "RefCell is already borrowed")]
468 fn cannot_replace_with_borrowed_refcell() {
469 let c = RefCell::new(5);
470 let _b = c.borrow();
471 c.replace_with(|&mut old_val| old_val + 1);
472 }
473
474 #[test]
475 #[should_panic(expected = "RefCell is already borrowed")]
476 fn cannot_replace_with_mut_borrowed_refcell() {
477 let c = RefCell::new(5);
478 let _b = c.borrow_mut();
479 c.replace_with(|&mut old_val| old_val + 1);
480 }
481}