@@ -8,7 +8,7 @@ use backtrace::Backtrace;
8
8
use std:: cell:: {
9
9
BorrowError , BorrowMutError , Ref as StdRef , RefCell as StdRefCell , RefMut as StdRefMut ,
10
10
} ;
11
- use std:: env;
11
+ use std:: { env, mem } ;
12
12
use std:: fmt:: { Debug , Display , Error , Formatter } ;
13
13
use std:: ops:: { Deref , DerefMut } ;
14
14
@@ -203,8 +203,8 @@ impl<T: ?Sized> RefCell<T> {
203
203
} )
204
204
}
205
205
206
- /// Borrow the value stored in this cell mutably. Panics if any outstanding immutable
207
- /// borrows of the same cell exist .
206
+ /// Borrow the value stored in this cell mutably. Panics if there are any other outstanding
207
+ /// borrows of this cell (mutable borrows are unique, i.e. there can only be one) .
208
208
pub fn borrow_mut ( & self ) -> RefMut < T > {
209
209
if let Ok ( r) = self . inner . try_borrow_mut ( ) {
210
210
let id = self . borrows . borrow_mut ( ) . record ( ) ;
@@ -225,7 +225,7 @@ impl<T: ?Sized> RefCell<T> {
225
225
}
226
226
}
227
227
}
228
- panic ! ( "RefCell is already immutably borrowed." ) ;
228
+ panic ! ( "RefCell is already borrowed." ) ;
229
229
}
230
230
}
231
231
@@ -251,6 +251,20 @@ impl<T: ?Sized> RefCell<T> {
251
251
}
252
252
}
253
253
254
+ impl < T > RefCell < T > {
255
+ /// Corresponds to https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.replace.
256
+ pub fn replace ( & self , t : T ) -> T {
257
+ mem:: replace ( & mut * self . borrow_mut ( ) , t)
258
+ }
259
+
260
+ /// Corresponds to https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.replace_with.
261
+ pub fn replace_with < F : FnOnce ( & mut T ) -> T > ( & self , f : F ) -> T {
262
+ let mut_borrow = & mut * self . borrow_mut ( ) ;
263
+ let replacement = f ( mut_borrow) ;
264
+ mem:: replace ( mut_borrow, replacement)
265
+ }
266
+ }
267
+
254
268
/// Print a backtrace without any frames from the backtrace library.
255
269
fn print_filtered_backtrace ( backtrace : & Backtrace ) {
256
270
let mut idx = 1 ;
@@ -284,6 +298,13 @@ impl<T: Clone> Clone for RefCell<T> {
284
298
}
285
299
}
286
300
301
+ impl < T : Default > RefCell < T > {
302
+ /// Corresponds to https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.take.
303
+ pub fn take ( & self ) -> T {
304
+ self . replace ( Default :: default ( ) )
305
+ }
306
+ }
307
+
287
308
impl < T : Default > Default for RefCell < T > {
288
309
fn default ( ) -> RefCell < T > {
289
310
RefCell :: new ( Default :: default ( ) )
@@ -319,7 +340,7 @@ mod tests {
319
340
use super :: { Ref , RefCell } ;
320
341
321
342
#[ test]
322
- #[ should_panic( expected = "RefCell is already immutably borrowed" ) ]
343
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
323
344
fn cannot_borrow_mutably ( ) {
324
345
let c = RefCell :: new ( 5 ) ;
325
346
let _b = c. borrow ( ) ;
@@ -358,4 +379,81 @@ mod tests {
358
379
} ;
359
380
let _b2 = c. borrow_mut ( ) ;
360
381
}
382
+
383
+ #[ test]
384
+ fn take_refcell_returns_correct_value ( ) {
385
+ let c = RefCell :: new ( 5 ) ;
386
+ assert_eq ! ( 5 , c. take( ) ) ;
387
+ assert_eq ! ( i32 :: default ( ) , * c. borrow( ) ) ;
388
+ }
389
+
390
+ #[ test]
391
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
392
+ fn cannot_take_borrowed_refcell ( ) {
393
+ let c = RefCell :: new ( 5 ) ;
394
+ let _b = c. borrow ( ) ;
395
+ c. take ( ) ;
396
+ }
397
+
398
+ #[ test]
399
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
400
+ fn cannot_take_mut_borrowed_refcell ( ) {
401
+ let c = RefCell :: new ( 5 ) ;
402
+ let _b = c. borrow_mut ( ) ;
403
+ c. take ( ) ;
404
+ }
405
+
406
+ #[ test]
407
+ fn replace_refcell_properly_replaces_contents ( ) {
408
+ let c = RefCell :: new ( 5 ) ;
409
+ c. replace ( 12 ) ;
410
+ assert_eq ! ( 12 , * c. borrow( ) ) ;
411
+ }
412
+
413
+ #[ test]
414
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
415
+ fn cannot_replace_borrowed_refcell ( ) {
416
+ let c = RefCell :: new ( 5 ) ;
417
+ let _b = c. borrow ( ) ;
418
+ c. replace ( 12 ) ;
419
+ }
420
+
421
+ #[ test]
422
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
423
+ fn cannot_replace_mut_borrowed_refcell ( ) {
424
+ let c = RefCell :: new ( 5 ) ;
425
+ let _b = c. borrow_mut ( ) ;
426
+ c. replace ( 12 ) ;
427
+ }
428
+
429
+ #[ test]
430
+ fn replace_with_refcell_properly_replaces_contents ( ) {
431
+ let c = RefCell :: new ( 5 ) ;
432
+ c. replace_with ( |& mut old_value| old_value + 1 ) ;
433
+ assert_eq ! ( 6 , * c. borrow( ) ) ;
434
+ }
435
+
436
+ #[ test]
437
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
438
+ fn cannot_replace_with_borrowed_refcell ( ) {
439
+ let c = RefCell :: new ( 5 ) ;
440
+ let _b = c. borrow ( ) ;
441
+ c. replace_with ( |& mut old_val| { old_val + 1 } ) ;
442
+ }
443
+
444
+ #[ test]
445
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
446
+ fn cannot_replace_with_mut_borrowed_refcell ( ) {
447
+ let c = RefCell :: new ( 5 ) ;
448
+ let _b = c. borrow_mut ( ) ;
449
+ c. replace_with ( |& mut old_val| { old_val + 1 } ) ;
450
+ }
451
+
452
+ #[ test]
453
+ #[ should_panic( expected = "RefCell is already borrowed" ) ]
454
+ fn test ( ) {
455
+ let c = RefCell :: new ( 5 ) ;
456
+ let _b = c. borrow_mut ( ) ;
457
+ let _b2 = c. borrow_mut ( ) ;
458
+ }
361
459
}
0 commit comments