@@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display};
255255use crate :: marker:: { PhantomData , PointerLike , Unsize } ;
256256use crate :: mem;
257257use crate :: ops:: { CoerceUnsized , Deref , DerefMut , DerefPure , DispatchFromDyn } ;
258+ use crate :: panic:: const_panic;
258259use crate :: pin:: PinCoerceUnsized ;
259260use crate :: ptr:: { self , NonNull } ;
260261
@@ -796,16 +797,24 @@ impl Display for BorrowMutError {
796797#[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) ) ]
797798#[ track_caller]
798799#[ cold]
799- fn panic_already_borrowed ( err : BorrowMutError ) -> ! {
800- panic ! ( "already borrowed: {:?}" , err)
800+ const fn panic_already_borrowed ( err : BorrowMutError ) -> ! {
801+ const_panic ! (
802+ "already borrowed" ,
803+ "already borrowed: {err:?}" ,
804+ err: BorrowMutError = err,
805+ )
801806}
802807
803808// This ensures the panicking code is outlined from `borrow` for `RefCell`.
804809#[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) ) ]
805810#[ track_caller]
806811#[ cold]
807- fn panic_already_mutably_borrowed ( err : BorrowError ) -> ! {
808- panic ! ( "already mutably borrowed: {:?}" , err)
812+ const fn panic_already_mutably_borrowed ( err : BorrowError ) -> ! {
813+ const_panic ! (
814+ "already mutably borrowed" ,
815+ "already mutably borrowed: {err:?}" ,
816+ err: BorrowError = err,
817+ )
809818}
810819
811820// Positive values represent the number of `Ref` active. Negative values
@@ -825,12 +834,12 @@ type BorrowFlag = isize;
825834const UNUSED : BorrowFlag = 0 ;
826835
827836#[ inline( always) ]
828- fn is_writing ( x : BorrowFlag ) -> bool {
837+ const fn is_writing ( x : BorrowFlag ) -> bool {
829838 x < UNUSED
830839}
831840
832841#[ inline( always) ]
833- fn is_reading ( x : BorrowFlag ) -> bool {
842+ const fn is_reading ( x : BorrowFlag ) -> bool {
834843 x > UNUSED
835844}
836845
@@ -899,8 +908,12 @@ impl<T> RefCell<T> {
899908 #[ stable( feature = "refcell_replace" , since = "1.24.0" ) ]
900909 #[ track_caller]
901910 #[ rustc_confusables( "swap" ) ]
902- pub fn replace ( & self , t : T ) -> T {
903- mem:: replace ( & mut * self . borrow_mut ( ) , t)
911+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
912+ pub const fn replace ( & self , t : T ) -> T {
913+ let mut s = self . borrow_mut ( ) ;
914+ let t = mem:: replace ( s. as_mut ( ) , t) ;
915+ s. const_drop ( ) ;
916+ t
904917 }
905918
906919 /// Replaces the wrapped value with a new one computed from `f`, returning
@@ -950,8 +963,13 @@ impl<T> RefCell<T> {
950963 /// ```
951964 #[ inline]
952965 #[ stable( feature = "refcell_swap" , since = "1.24.0" ) ]
953- pub fn swap ( & self , other : & Self ) {
954- mem:: swap ( & mut * self . borrow_mut ( ) , & mut * other. borrow_mut ( ) )
966+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
967+ pub const fn swap ( & self , other : & Self ) {
968+ let mut s = self . borrow_mut ( ) ;
969+ let mut o = other. borrow_mut ( ) ;
970+ mem:: swap ( s. as_mut ( ) , o. as_mut ( ) ) ;
971+ s. const_drop ( ) ;
972+ o. const_drop ( ) ;
955973 }
956974}
957975
@@ -990,7 +1008,8 @@ impl<T: ?Sized> RefCell<T> {
9901008 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
9911009 #[ inline]
9921010 #[ track_caller]
993- pub fn borrow ( & self ) -> Ref < ' _ , T > {
1011+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1012+ pub const fn borrow ( & self ) -> Ref < ' _ , T > {
9941013 match self . try_borrow ( ) {
9951014 Ok ( b) => b,
9961015 Err ( err) => panic_already_mutably_borrowed ( err) ,
@@ -1025,14 +1044,15 @@ impl<T: ?Sized> RefCell<T> {
10251044 #[ stable( feature = "try_borrow" , since = "1.13.0" ) ]
10261045 #[ inline]
10271046 #[ cfg_attr( feature = "debug_refcell" , track_caller) ]
1028- pub fn try_borrow ( & self ) -> Result < Ref < ' _ , T > , BorrowError > {
1047+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1048+ pub const fn try_borrow ( & self ) -> Result < Ref < ' _ , T > , BorrowError > {
10291049 match BorrowRef :: new ( & self . borrow ) {
10301050 Some ( b) => {
10311051 #[ cfg( feature = "debug_refcell" ) ]
10321052 {
10331053 // `borrowed_at` is always the *first* active borrow
10341054 if b. borrow . get ( ) == 1 {
1035- self . borrowed_at . set ( Some ( crate :: panic:: Location :: caller ( ) ) ) ;
1055+ self . borrowed_at . replace ( Some ( crate :: panic:: Location :: caller ( ) ) ) ;
10361056 }
10371057 }
10381058
@@ -1086,7 +1106,8 @@ impl<T: ?Sized> RefCell<T> {
10861106 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
10871107 #[ inline]
10881108 #[ track_caller]
1089- pub fn borrow_mut ( & self ) -> RefMut < ' _ , T > {
1109+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1110+ pub const fn borrow_mut ( & self ) -> RefMut < ' _ , T > {
10901111 match self . try_borrow_mut ( ) {
10911112 Ok ( b) => b,
10921113 Err ( err) => panic_already_borrowed ( err) ,
@@ -1118,12 +1139,13 @@ impl<T: ?Sized> RefCell<T> {
11181139 #[ stable( feature = "try_borrow" , since = "1.13.0" ) ]
11191140 #[ inline]
11201141 #[ cfg_attr( feature = "debug_refcell" , track_caller) ]
1121- pub fn try_borrow_mut ( & self ) -> Result < RefMut < ' _ , T > , BorrowMutError > {
1142+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1143+ pub const fn try_borrow_mut ( & self ) -> Result < RefMut < ' _ , T > , BorrowMutError > {
11221144 match BorrowRefMut :: new ( & self . borrow ) {
11231145 Some ( b) => {
11241146 #[ cfg( feature = "debug_refcell" ) ]
11251147 {
1126- self . borrowed_at . set ( Some ( crate :: panic:: Location :: caller ( ) ) ) ;
1148+ self . borrowed_at . replace ( Some ( crate :: panic:: Location :: caller ( ) ) ) ;
11271149 }
11281150
11291151 // SAFETY: `BorrowRefMut` guarantees unique access.
@@ -1154,7 +1176,8 @@ impl<T: ?Sized> RefCell<T> {
11541176 #[ stable( feature = "cell_as_ptr" , since = "1.12.0" ) ]
11551177 #[ rustc_as_ptr]
11561178 #[ rustc_never_returns_null_ptr]
1157- pub fn as_ptr ( & self ) -> * mut T {
1179+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1180+ pub const fn as_ptr ( & self ) -> * mut T {
11581181 self . value . get ( )
11591182 }
11601183
@@ -1187,7 +1210,8 @@ impl<T: ?Sized> RefCell<T> {
11871210 /// ```
11881211 #[ inline]
11891212 #[ stable( feature = "cell_get_mut" , since = "1.11.0" ) ]
1190- pub fn get_mut ( & mut self ) -> & mut T {
1213+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1214+ pub const fn get_mut ( & mut self ) -> & mut T {
11911215 self . value . get_mut ( )
11921216 }
11931217
@@ -1213,7 +1237,8 @@ impl<T: ?Sized> RefCell<T> {
12131237 /// assert!(c.try_borrow().is_ok());
12141238 /// ```
12151239 #[ unstable( feature = "cell_leak" , issue = "69099" ) ]
1216- pub fn undo_leak ( & mut self ) -> & mut T {
1240+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1241+ pub const fn undo_leak ( & mut self ) -> & mut T {
12171242 * self . borrow . get_mut ( ) = UNUSED ;
12181243 self . get_mut ( )
12191244 }
@@ -1247,7 +1272,8 @@ impl<T: ?Sized> RefCell<T> {
12471272 /// ```
12481273 #[ stable( feature = "borrow_state" , since = "1.37.0" ) ]
12491274 #[ inline]
1250- pub unsafe fn try_borrow_unguarded ( & self ) -> Result < & T , BorrowError > {
1275+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1276+ pub const unsafe fn try_borrow_unguarded ( & self ) -> Result < & T , BorrowError > {
12511277 if !is_writing ( self . borrow . get ( ) ) {
12521278 // SAFETY: We check that nobody is actively writing now, but it is
12531279 // the caller's responsibility to ensure that nobody writes until
@@ -1411,7 +1437,8 @@ struct BorrowRef<'b> {
14111437
14121438impl < ' b > BorrowRef < ' b > {
14131439 #[ inline]
1414- fn new ( borrow : & ' b Cell < BorrowFlag > ) -> Option < BorrowRef < ' b > > {
1440+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1441+ const fn new ( borrow : & ' b Cell < BorrowFlag > ) -> Option < BorrowRef < ' b > > {
14151442 let b = borrow. get ( ) . wrapping_add ( 1 ) ;
14161443 if !is_reading ( b) {
14171444 // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
@@ -1428,10 +1455,23 @@ impl<'b> BorrowRef<'b> {
14281455 // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
14291456 // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
14301457 // is large enough to represent having one more read borrow
1431- borrow. set ( b) ;
1458+ borrow. replace ( b) ;
14321459 Some ( BorrowRef { borrow } )
14331460 }
14341461 }
1462+ #[ inline]
1463+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1464+ const fn clone ( & self ) -> Self {
1465+ // Since this Ref exists, we know the borrow flag
1466+ // is a reading borrow.
1467+ let borrow = self . borrow . get ( ) ;
1468+ debug_assert ! ( is_reading( borrow) ) ;
1469+ // Prevent the borrow counter from overflowing into
1470+ // a writing borrow.
1471+ assert ! ( borrow != BorrowFlag :: MAX ) ;
1472+ self . borrow . replace ( borrow + 1 ) ;
1473+ BorrowRef { borrow : self . borrow }
1474+ }
14351475}
14361476
14371477impl Drop for BorrowRef < ' _ > {
@@ -1446,15 +1486,7 @@ impl Drop for BorrowRef<'_> {
14461486impl Clone for BorrowRef < ' _ > {
14471487 #[ inline]
14481488 fn clone ( & self ) -> Self {
1449- // Since this Ref exists, we know the borrow flag
1450- // is a reading borrow.
1451- let borrow = self . borrow . get ( ) ;
1452- debug_assert ! ( is_reading( borrow) ) ;
1453- // Prevent the borrow counter from overflowing into
1454- // a writing borrow.
1455- assert ! ( borrow != BorrowFlag :: MAX ) ;
1456- self . borrow . set ( borrow + 1 ) ;
1457- BorrowRef { borrow : self . borrow }
1489+ self . clone ( )
14581490 }
14591491}
14601492
@@ -1499,7 +1531,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
14991531 #[ stable( feature = "cell_extras" , since = "1.15.0" ) ]
15001532 #[ must_use]
15011533 #[ inline]
1502- pub fn clone ( orig : & Ref < ' b , T > ) -> Ref < ' b , T > {
1534+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1535+ pub const fn clone ( orig : & Ref < ' b , T > ) -> Ref < ' b , T > {
15031536 Ref { value : orig. value , borrow : orig. borrow . clone ( ) }
15041537 }
15051538
@@ -1621,7 +1654,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
16211654 /// assert!(cell.try_borrow_mut().is_err());
16221655 /// ```
16231656 #[ unstable( feature = "cell_leak" , issue = "69099" ) ]
1624- pub fn leak ( orig : Ref < ' b , T > ) -> & ' b T {
1657+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1658+ pub const fn leak ( orig : Ref < ' b , T > ) -> & ' b T {
16251659 // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
16261660 // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
16271661 // unique reference to the borrowed RefCell. No further mutable references can be created
@@ -1643,6 +1677,21 @@ impl<T: ?Sized + fmt::Display> fmt::Display for Ref<'_, T> {
16431677}
16441678
16451679impl < ' b , T : ?Sized > RefMut < ' b , T > {
1680+ #[ inline]
1681+ const fn as_mut ( & mut self ) -> & mut T {
1682+ // SAFETY: the value is accessible as long as we hold our borrow.
1683+ unsafe { self . value . as_mut ( ) }
1684+ }
1685+
1686+ #[ inline]
1687+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1688+ const fn const_drop ( self ) {
1689+ // SAFETY: only `borrow` is `Drop`
1690+ let borrow = unsafe { ptr:: read ( & self . borrow ) } ;
1691+ mem:: forget ( self ) ;
1692+ borrow. const_drop ( ) ;
1693+ }
1694+
16461695 /// Makes a new `RefMut` for a component of the borrowed data, e.g., an enum
16471696 /// variant.
16481697 ///
@@ -1787,7 +1836,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
17871836 /// assert!(cell.try_borrow_mut().is_err());
17881837 /// ```
17891838 #[ unstable( feature = "cell_leak" , issue = "69099" ) ]
1790- pub fn leak ( mut orig : RefMut < ' b , T > ) -> & ' b mut T {
1839+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1840+ pub const fn leak ( mut orig : RefMut < ' b , T > ) -> & ' b mut T {
17911841 // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
17921842 // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
17931843 // require a unique reference to the borrowed RefCell. No further references can be created
@@ -1814,14 +1864,24 @@ impl Drop for BorrowRefMut<'_> {
18141864
18151865impl < ' b > BorrowRefMut < ' b > {
18161866 #[ inline]
1817- fn new ( borrow : & ' b Cell < BorrowFlag > ) -> Option < BorrowRefMut < ' b > > {
1867+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1868+ const fn const_drop ( self ) {
1869+ let borrow = self . borrow . get ( ) ;
1870+ debug_assert ! ( is_writing( borrow) ) ;
1871+ self . borrow . replace ( borrow + 1 ) ;
1872+ mem:: forget ( self )
1873+ }
1874+
1875+ #[ inline]
1876+ #[ rustc_const_unstable( feature = "const_ref_cell" , issue = "137844" ) ]
1877+ const fn new ( borrow : & ' b Cell < BorrowFlag > ) -> Option < BorrowRefMut < ' b > > {
18181878 // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
18191879 // mutable reference, and so there must currently be no existing
18201880 // references. Thus, while clone increments the mutable refcount, here
18211881 // we explicitly only allow going from UNUSED to UNUSED - 1.
18221882 match borrow. get ( ) {
18231883 UNUSED => {
1824- borrow. set ( UNUSED - 1 ) ;
1884+ borrow. replace ( UNUSED - 1 ) ;
18251885 Some ( BorrowRefMut { borrow } )
18261886 }
18271887 _ => None ,
@@ -1874,8 +1934,7 @@ impl<T: ?Sized> Deref for RefMut<'_, T> {
18741934impl < T : ?Sized > DerefMut for RefMut < ' _ , T > {
18751935 #[ inline]
18761936 fn deref_mut ( & mut self ) -> & mut T {
1877- // SAFETY: the value is accessible as long as we hold our borrow.
1878- unsafe { self . value . as_mut ( ) }
1937+ self . as_mut ( )
18791938 }
18801939}
18811940
0 commit comments