147
147
use clone:: Clone ;
148
148
use cmp:: { PartialEq , Eq , PartialOrd , Ord , Ordering } ;
149
149
use default:: Default ;
150
- use marker:: { Copy , Send , Sync , Sized , Unsize } ;
150
+ use fmt:: { self , Debug , Display } ;
151
+ use marker:: { Copy , PhantomData , Send , Sync , Sized , Unsize } ;
151
152
use ops:: { Deref , DerefMut , Drop , FnOnce , CoerceUnsized } ;
152
153
use option:: Option ;
153
154
use option:: Option :: { None , Some } ;
155
+ use result:: Result ;
156
+ use result:: Result :: { Ok , Err } ;
154
157
155
158
/// A mutable memory location that admits only `Copy` data.
156
159
///
@@ -347,6 +350,46 @@ pub enum BorrowState {
347
350
Unused ,
348
351
}
349
352
353
+ /// An error returned by [`RefCell::try_borrow`](struct.RefCell.html#method.try_borrow).
354
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
355
+ pub struct BorrowError < ' a , T : ' a + ?Sized > {
356
+ marker : PhantomData < & ' a RefCell < T > > ,
357
+ }
358
+
359
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
360
+ impl < ' a , T : ?Sized > Debug for BorrowError < ' a , T > {
361
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
362
+ f. debug_struct ( "BorrowError" ) . finish ( )
363
+ }
364
+ }
365
+
366
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
367
+ impl < ' a , T : ?Sized > Display for BorrowError < ' a , T > {
368
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
369
+ Display :: fmt ( "already mutably borrowed" , f)
370
+ }
371
+ }
372
+
373
+ /// An error returned by [`RefCell::try_borrow_mut`](struct.RefCell.html#method.try_borrow_mut).
374
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
375
+ pub struct BorrowMutError < ' a , T : ' a + ?Sized > {
376
+ marker : PhantomData < & ' a RefCell < T > > ,
377
+ }
378
+
379
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
380
+ impl < ' a , T : ?Sized > Debug for BorrowMutError < ' a , T > {
381
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
382
+ f. debug_struct ( "BorrowMutError" ) . finish ( )
383
+ }
384
+ }
385
+
386
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
387
+ impl < ' a , T : ?Sized > Display for BorrowMutError < ' a , T > {
388
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
389
+ Display :: fmt ( "already borrowed" , f)
390
+ }
391
+ }
392
+
350
393
// Values [1, MAX-1] represent the number of `Ref` active
351
394
// (will not outgrow its range since `usize` is the size of the address space)
352
395
type BorrowFlag = usize ;
@@ -432,7 +475,8 @@ impl<T: ?Sized> RefCell<T> {
432
475
///
433
476
/// # Panics
434
477
///
435
- /// Panics if the value is currently mutably borrowed.
478
+ /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
479
+ /// [`try_borrow`](#method.try_borrow).
436
480
///
437
481
/// # Examples
438
482
///
@@ -463,12 +507,45 @@ impl<T: ?Sized> RefCell<T> {
463
507
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
464
508
#[ inline]
465
509
pub fn borrow ( & self ) -> Ref < T > {
510
+ self . try_borrow ( ) . expect ( "already mutably borrowed" )
511
+ }
512
+
513
+ /// Immutably borrows the wrapped value, returning an error if the value is currently mutably
514
+ /// borrowed.
515
+ ///
516
+ /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be
517
+ /// taken out at the same time.
518
+ ///
519
+ /// This is the non-panicking variant of [`borrow`](#method.borrow).
520
+ ///
521
+ /// # Examples
522
+ ///
523
+ /// ```
524
+ /// #![feature(try_borrow)]
525
+ ///
526
+ /// use std::cell::RefCell;
527
+ ///
528
+ /// let c = RefCell::new(5);
529
+ ///
530
+ /// {
531
+ /// let m = c.borrow_mut();
532
+ /// assert!(c.try_borrow().is_err());
533
+ /// }
534
+ ///
535
+ /// {
536
+ /// let m = c.borrow();
537
+ /// assert!(c.try_borrow().is_ok());
538
+ /// }
539
+ /// ```
540
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
541
+ #[ inline]
542
+ pub fn try_borrow ( & self ) -> Result < Ref < T > , BorrowError < T > > {
466
543
match BorrowRef :: new ( & self . borrow ) {
467
- Some ( b) => Ref {
544
+ Some ( b) => Ok ( Ref {
468
545
value : unsafe { & * self . value . get ( ) } ,
469
546
borrow : b,
470
- } ,
471
- None => panic ! ( "RefCell<T> already mutably borrowed" ) ,
547
+ } ) ,
548
+ None => Err ( BorrowError { marker : PhantomData } ) ,
472
549
}
473
550
}
474
551
@@ -479,7 +556,8 @@ impl<T: ?Sized> RefCell<T> {
479
556
///
480
557
/// # Panics
481
558
///
482
- /// Panics if the value is currently borrowed.
559
+ /// Panics if the value is currently borrowed. For a non-panicking variant, use
560
+ /// [`try_borrow_mut`](#method.try_borrow_mut).
483
561
///
484
562
/// # Examples
485
563
///
@@ -511,12 +589,41 @@ impl<T: ?Sized> RefCell<T> {
511
589
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
512
590
#[ inline]
513
591
pub fn borrow_mut ( & self ) -> RefMut < T > {
592
+ self . try_borrow_mut ( ) . expect ( "already borrowed" )
593
+ }
594
+
595
+ /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
596
+ ///
597
+ /// The borrow lasts until the returned `RefMut` exits scope. The value cannot be borrowed
598
+ /// while this borrow is active.
599
+ ///
600
+ /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
601
+ ///
602
+ /// # Examples
603
+ ///
604
+ /// ```
605
+ /// #![feature(try_borrow)]
606
+ ///
607
+ /// use std::cell::RefCell;
608
+ ///
609
+ /// let c = RefCell::new(5);
610
+ ///
611
+ /// {
612
+ /// let m = c.borrow();
613
+ /// assert!(c.try_borrow_mut().is_err());
614
+ /// }
615
+ ///
616
+ /// assert!(c.try_borrow_mut().is_ok());
617
+ /// ```
618
+ #[ unstable( feature = "try_borrow" , issue = "35070" ) ]
619
+ #[ inline]
620
+ pub fn try_borrow_mut ( & self ) -> Result < RefMut < T > , BorrowMutError < T > > {
514
621
match BorrowRefMut :: new ( & self . borrow ) {
515
- Some ( b) => RefMut {
622
+ Some ( b) => Ok ( RefMut {
516
623
value : unsafe { & mut * self . value . get ( ) } ,
517
624
borrow : b,
518
- } ,
519
- None => panic ! ( "RefCell<T> already borrowed" ) ,
625
+ } ) ,
626
+ None => Err ( BorrowMutError { marker : PhantomData } ) ,
520
627
}
521
628
}
522
629
0 commit comments