147147use clone:: Clone ;
148148use cmp:: { PartialEq , Eq , PartialOrd , Ord , Ordering } ;
149149use 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 } ;
151152use ops:: { Deref , DerefMut , Drop , FnOnce , CoerceUnsized } ;
152153use option:: Option ;
153154use option:: Option :: { None , Some } ;
155+ use result:: Result ;
156+ use result:: Result :: { Ok , Err } ;
154157
155158/// A mutable memory location that admits only `Copy` data.
156159///
@@ -347,6 +350,46 @@ pub enum BorrowState {
347350 Unused ,
348351}
349352
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+
350393// Values [1, MAX-1] represent the number of `Ref` active
351394// (will not outgrow its range since `usize` is the size of the address space)
352395type BorrowFlag = usize ;
@@ -432,7 +475,8 @@ impl<T: ?Sized> RefCell<T> {
432475 ///
433476 /// # Panics
434477 ///
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).
436480 ///
437481 /// # Examples
438482 ///
@@ -463,12 +507,45 @@ impl<T: ?Sized> RefCell<T> {
463507 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
464508 #[ inline]
465509 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 > > {
466543 match BorrowRef :: new ( & self . borrow ) {
467- Some ( b) => Ref {
544+ Some ( b) => Ok ( Ref {
468545 value : unsafe { & * self . value . get ( ) } ,
469546 borrow : b,
470- } ,
471- None => panic ! ( "RefCell<T> already mutably borrowed" ) ,
547+ } ) ,
548+ None => Err ( BorrowError { marker : PhantomData } ) ,
472549 }
473550 }
474551
@@ -479,7 +556,8 @@ impl<T: ?Sized> RefCell<T> {
479556 ///
480557 /// # Panics
481558 ///
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).
483561 ///
484562 /// # Examples
485563 ///
@@ -511,12 +589,41 @@ impl<T: ?Sized> RefCell<T> {
511589 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
512590 #[ inline]
513591 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 > > {
514621 match BorrowRefMut :: new ( & self . borrow ) {
515- Some ( b) => RefMut {
622+ Some ( b) => Ok ( RefMut {
516623 value : unsafe { & mut * self . value . get ( ) } ,
517624 borrow : b,
518- } ,
519- None => panic ! ( "RefCell<T> already borrowed" ) ,
625+ } ) ,
626+ None => Err ( BorrowMutError { marker : PhantomData } ) ,
520627 }
521628 }
522629
0 commit comments