@@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display};
255
255
use crate :: marker:: { PhantomData , PointerLike , Unsize } ;
256
256
use crate :: mem;
257
257
use crate :: ops:: { CoerceUnsized , Deref , DerefMut , DerefPure , DispatchFromDyn } ;
258
+ use crate :: panic:: const_panic;
258
259
use crate :: pin:: PinCoerceUnsized ;
259
260
use crate :: ptr:: { self , NonNull } ;
260
261
@@ -796,16 +797,24 @@ impl Display for BorrowMutError {
796
797
#[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) ) ]
797
798
#[ track_caller]
798
799
#[ 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
+ )
801
806
}
802
807
803
808
// This ensures the panicking code is outlined from `borrow` for `RefCell`.
804
809
#[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) ) ]
805
810
#[ track_caller]
806
811
#[ 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
+ )
809
818
}
810
819
811
820
// Positive values represent the number of `Ref` active. Negative values
@@ -825,12 +834,12 @@ type BorrowFlag = isize;
825
834
const UNUSED : BorrowFlag = 0 ;
826
835
827
836
#[ inline( always) ]
828
- fn is_writing ( x : BorrowFlag ) -> bool {
837
+ const fn is_writing ( x : BorrowFlag ) -> bool {
829
838
x < UNUSED
830
839
}
831
840
832
841
#[ inline( always) ]
833
- fn is_reading ( x : BorrowFlag ) -> bool {
842
+ const fn is_reading ( x : BorrowFlag ) -> bool {
834
843
x > UNUSED
835
844
}
836
845
@@ -899,8 +908,12 @@ impl<T> RefCell<T> {
899
908
#[ stable( feature = "refcell_replace" , since = "1.24.0" ) ]
900
909
#[ track_caller]
901
910
#[ 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
904
917
}
905
918
906
919
/// Replaces the wrapped value with a new one computed from `f`, returning
@@ -950,8 +963,13 @@ impl<T> RefCell<T> {
950
963
/// ```
951
964
#[ inline]
952
965
#[ 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 ( ) ;
955
973
}
956
974
}
957
975
@@ -990,7 +1008,8 @@ impl<T: ?Sized> RefCell<T> {
990
1008
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
991
1009
#[ inline]
992
1010
#[ 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 > {
994
1013
match self . try_borrow ( ) {
995
1014
Ok ( b) => b,
996
1015
Err ( err) => panic_already_mutably_borrowed ( err) ,
@@ -1025,14 +1044,15 @@ impl<T: ?Sized> RefCell<T> {
1025
1044
#[ stable( feature = "try_borrow" , since = "1.13.0" ) ]
1026
1045
#[ inline]
1027
1046
#[ 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 > {
1029
1049
match BorrowRef :: new ( & self . borrow ) {
1030
1050
Some ( b) => {
1031
1051
#[ cfg( feature = "debug_refcell" ) ]
1032
1052
{
1033
1053
// `borrowed_at` is always the *first* active borrow
1034
1054
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 ( ) ) ) ;
1036
1056
}
1037
1057
}
1038
1058
@@ -1086,7 +1106,8 @@ impl<T: ?Sized> RefCell<T> {
1086
1106
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1087
1107
#[ inline]
1088
1108
#[ 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 > {
1090
1111
match self . try_borrow_mut ( ) {
1091
1112
Ok ( b) => b,
1092
1113
Err ( err) => panic_already_borrowed ( err) ,
@@ -1118,12 +1139,13 @@ impl<T: ?Sized> RefCell<T> {
1118
1139
#[ stable( feature = "try_borrow" , since = "1.13.0" ) ]
1119
1140
#[ inline]
1120
1141
#[ 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 > {
1122
1144
match BorrowRefMut :: new ( & self . borrow ) {
1123
1145
Some ( b) => {
1124
1146
#[ cfg( feature = "debug_refcell" ) ]
1125
1147
{
1126
- self . borrowed_at . set ( Some ( crate :: panic:: Location :: caller ( ) ) ) ;
1148
+ self . borrowed_at . replace ( Some ( crate :: panic:: Location :: caller ( ) ) ) ;
1127
1149
}
1128
1150
1129
1151
// SAFETY: `BorrowRefMut` guarantees unique access.
@@ -1154,7 +1176,8 @@ impl<T: ?Sized> RefCell<T> {
1154
1176
#[ stable( feature = "cell_as_ptr" , since = "1.12.0" ) ]
1155
1177
#[ rustc_as_ptr]
1156
1178
#[ 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 {
1158
1181
self . value . get ( )
1159
1182
}
1160
1183
@@ -1187,7 +1210,8 @@ impl<T: ?Sized> RefCell<T> {
1187
1210
/// ```
1188
1211
#[ inline]
1189
1212
#[ 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 {
1191
1215
self . value . get_mut ( )
1192
1216
}
1193
1217
@@ -1213,7 +1237,8 @@ impl<T: ?Sized> RefCell<T> {
1213
1237
/// assert!(c.try_borrow().is_ok());
1214
1238
/// ```
1215
1239
#[ 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 {
1217
1242
* self . borrow . get_mut ( ) = UNUSED ;
1218
1243
self . get_mut ( )
1219
1244
}
@@ -1247,7 +1272,8 @@ impl<T: ?Sized> RefCell<T> {
1247
1272
/// ```
1248
1273
#[ stable( feature = "borrow_state" , since = "1.37.0" ) ]
1249
1274
#[ 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 > {
1251
1277
if !is_writing ( self . borrow . get ( ) ) {
1252
1278
// SAFETY: We check that nobody is actively writing now, but it is
1253
1279
// the caller's responsibility to ensure that nobody writes until
@@ -1411,7 +1437,8 @@ struct BorrowRef<'b> {
1411
1437
1412
1438
impl < ' b > BorrowRef < ' b > {
1413
1439
#[ 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 > > {
1415
1442
let b = borrow. get ( ) . wrapping_add ( 1 ) ;
1416
1443
if !is_reading ( b) {
1417
1444
// Incrementing borrow can result in a non-reading value (<= 0) in these cases:
@@ -1428,10 +1455,23 @@ impl<'b> BorrowRef<'b> {
1428
1455
// 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
1429
1456
// 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
1430
1457
// is large enough to represent having one more read borrow
1431
- borrow. set ( b) ;
1458
+ borrow. replace ( b) ;
1432
1459
Some ( BorrowRef { borrow } )
1433
1460
}
1434
1461
}
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
+ }
1435
1475
}
1436
1476
1437
1477
impl Drop for BorrowRef < ' _ > {
@@ -1446,15 +1486,7 @@ impl Drop for BorrowRef<'_> {
1446
1486
impl Clone for BorrowRef < ' _ > {
1447
1487
#[ inline]
1448
1488
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 ( )
1458
1490
}
1459
1491
}
1460
1492
@@ -1499,7 +1531,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
1499
1531
#[ stable( feature = "cell_extras" , since = "1.15.0" ) ]
1500
1532
#[ must_use]
1501
1533
#[ 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 > {
1503
1536
Ref { value : orig. value , borrow : orig. borrow . clone ( ) }
1504
1537
}
1505
1538
@@ -1621,7 +1654,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
1621
1654
/// assert!(cell.try_borrow_mut().is_err());
1622
1655
/// ```
1623
1656
#[ 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 {
1625
1659
// By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
1626
1660
// UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
1627
1661
// 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> {
1643
1677
}
1644
1678
1645
1679
impl < ' 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
+
1646
1695
/// Makes a new `RefMut` for a component of the borrowed data, e.g., an enum
1647
1696
/// variant.
1648
1697
///
@@ -1787,7 +1836,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
1787
1836
/// assert!(cell.try_borrow_mut().is_err());
1788
1837
/// ```
1789
1838
#[ 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 {
1791
1841
// By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
1792
1842
// go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
1793
1843
// require a unique reference to the borrowed RefCell. No further references can be created
@@ -1814,14 +1864,24 @@ impl Drop for BorrowRefMut<'_> {
1814
1864
1815
1865
impl < ' b > BorrowRefMut < ' b > {
1816
1866
#[ 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 > > {
1818
1878
// NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
1819
1879
// mutable reference, and so there must currently be no existing
1820
1880
// references. Thus, while clone increments the mutable refcount, here
1821
1881
// we explicitly only allow going from UNUSED to UNUSED - 1.
1822
1882
match borrow. get ( ) {
1823
1883
UNUSED => {
1824
- borrow. set ( UNUSED - 1 ) ;
1884
+ borrow. replace ( UNUSED - 1 ) ;
1825
1885
Some ( BorrowRefMut { borrow } )
1826
1886
}
1827
1887
_ => None ,
@@ -1874,8 +1934,7 @@ impl<T: ?Sized> Deref for RefMut<'_, T> {
1874
1934
impl < T : ?Sized > DerefMut for RefMut < ' _ , T > {
1875
1935
#[ inline]
1876
1936
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 ( )
1879
1938
}
1880
1939
}
1881
1940
0 commit comments