Skip to content

Commit 7b9bde3

Browse files
make RefCell unstably const
1 parent e9f8103 commit 7b9bde3

File tree

4 files changed

+155
-42
lines changed

4 files changed

+155
-42
lines changed

library/core/src/cell.rs

+78-42
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display};
255255
use crate::marker::{PhantomData, PointerLike, Unsize};
256256
use crate::mem;
257257
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
258+
use crate::panic::const_panic;
258259
use crate::pin::PinCoerceUnsized;
259260
use crate::ptr::{self, NonNull};
260261

@@ -787,16 +788,24 @@ impl Display for BorrowMutError {
787788
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
788789
#[track_caller]
789790
#[cold]
790-
fn panic_already_borrowed(err: BorrowMutError) -> ! {
791-
panic!("already borrowed: {:?}", err)
791+
const fn panic_already_borrowed(err: BorrowMutError) -> ! {
792+
const_panic!(
793+
"already borrowed",
794+
"already borrowed: {err:?}",
795+
err: BorrowMutError = err,
796+
)
792797
}
793798

794799
// This ensures the panicking code is outlined from `borrow` for `RefCell`.
795800
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
796801
#[track_caller]
797802
#[cold]
798-
fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
799-
panic!("already mutably borrowed: {:?}", err)
803+
const fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
804+
const_panic!(
805+
"already mutably borrowed",
806+
"already mutably borrowed: {err:?}",
807+
err: BorrowError = err,
808+
)
800809
}
801810

802811
// Positive values represent the number of `Ref` active. Negative values
@@ -816,12 +825,12 @@ type BorrowFlag = isize;
816825
const UNUSED: BorrowFlag = 0;
817826

818827
#[inline(always)]
819-
fn is_writing(x: BorrowFlag) -> bool {
828+
const fn is_writing(x: BorrowFlag) -> bool {
820829
x < UNUSED
821830
}
822831

823832
#[inline(always)]
824-
fn is_reading(x: BorrowFlag) -> bool {
833+
const fn is_reading(x: BorrowFlag) -> bool {
825834
x > UNUSED
826835
}
827836

@@ -890,8 +899,9 @@ impl<T> RefCell<T> {
890899
#[stable(feature = "refcell_replace", since = "1.24.0")]
891900
#[track_caller]
892901
#[rustc_confusables("swap")]
893-
pub fn replace(&self, t: T) -> T {
894-
mem::replace(&mut *self.borrow_mut(), t)
902+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
903+
pub const fn replace(&self, t: T) -> T {
904+
mem::replace(&mut self.borrow_mut(), t)
895905
}
896906

897907
/// Replaces the wrapped value with a new one computed from `f`, returning
@@ -941,7 +951,8 @@ impl<T> RefCell<T> {
941951
/// ```
942952
#[inline]
943953
#[stable(feature = "refcell_swap", since = "1.24.0")]
944-
pub fn swap(&self, other: &Self) {
954+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
955+
pub const fn swap(&self, other: &Self) {
945956
mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
946957
}
947958
}
@@ -981,7 +992,8 @@ impl<T: ?Sized> RefCell<T> {
981992
#[stable(feature = "rust1", since = "1.0.0")]
982993
#[inline]
983994
#[track_caller]
984-
pub fn borrow(&self) -> Ref<'_, T> {
995+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
996+
pub const fn borrow(&self) -> Ref<'_, T> {
985997
match self.try_borrow() {
986998
Ok(b) => b,
987999
Err(err) => panic_already_mutably_borrowed(err),
@@ -1016,14 +1028,15 @@ impl<T: ?Sized> RefCell<T> {
10161028
#[stable(feature = "try_borrow", since = "1.13.0")]
10171029
#[inline]
10181030
#[cfg_attr(feature = "debug_refcell", track_caller)]
1019-
pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
1031+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1032+
pub const fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
10201033
match BorrowRef::new(&self.borrow) {
10211034
Some(b) => {
10221035
#[cfg(feature = "debug_refcell")]
10231036
{
10241037
// `borrowed_at` is always the *first* active borrow
10251038
if b.borrow.get() == 1 {
1026-
self.borrowed_at.set(Some(crate::panic::Location::caller()));
1039+
self.borrowed_at.replace(Some(crate::panic::Location::caller()));
10271040
}
10281041
}
10291042

@@ -1077,7 +1090,8 @@ impl<T: ?Sized> RefCell<T> {
10771090
#[stable(feature = "rust1", since = "1.0.0")]
10781091
#[inline]
10791092
#[track_caller]
1080-
pub fn borrow_mut(&self) -> RefMut<'_, T> {
1093+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1094+
pub const fn borrow_mut(&self) -> RefMut<'_, T> {
10811095
match self.try_borrow_mut() {
10821096
Ok(b) => b,
10831097
Err(err) => panic_already_borrowed(err),
@@ -1109,12 +1123,13 @@ impl<T: ?Sized> RefCell<T> {
11091123
#[stable(feature = "try_borrow", since = "1.13.0")]
11101124
#[inline]
11111125
#[cfg_attr(feature = "debug_refcell", track_caller)]
1112-
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
1126+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1127+
pub const fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
11131128
match BorrowRefMut::new(&self.borrow) {
11141129
Some(b) => {
11151130
#[cfg(feature = "debug_refcell")]
11161131
{
1117-
self.borrowed_at.set(Some(crate::panic::Location::caller()));
1132+
self.borrowed_at.replace(Some(crate::panic::Location::caller()));
11181133
}
11191134

11201135
// SAFETY: `BorrowRefMut` guarantees unique access.
@@ -1145,7 +1160,8 @@ impl<T: ?Sized> RefCell<T> {
11451160
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
11461161
#[rustc_as_ptr]
11471162
#[rustc_never_returns_null_ptr]
1148-
pub fn as_ptr(&self) -> *mut T {
1163+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1164+
pub const fn as_ptr(&self) -> *mut T {
11491165
self.value.get()
11501166
}
11511167

@@ -1182,7 +1198,8 @@ impl<T: ?Sized> RefCell<T> {
11821198
/// ```
11831199
#[inline]
11841200
#[stable(feature = "cell_get_mut", since = "1.11.0")]
1185-
pub fn get_mut(&mut self) -> &mut T {
1201+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1202+
pub const fn get_mut(&mut self) -> &mut T {
11861203
self.value.get_mut()
11871204
}
11881205

@@ -1208,7 +1225,8 @@ impl<T: ?Sized> RefCell<T> {
12081225
/// assert!(c.try_borrow().is_ok());
12091226
/// ```
12101227
#[unstable(feature = "cell_leak", issue = "69099")]
1211-
pub fn undo_leak(&mut self) -> &mut T {
1228+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1229+
pub const fn undo_leak(&mut self) -> &mut T {
12121230
*self.borrow.get_mut() = UNUSED;
12131231
self.get_mut()
12141232
}
@@ -1242,7 +1260,8 @@ impl<T: ?Sized> RefCell<T> {
12421260
/// ```
12431261
#[stable(feature = "borrow_state", since = "1.37.0")]
12441262
#[inline]
1245-
pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
1263+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1264+
pub const unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
12461265
if !is_writing(self.borrow.get()) {
12471266
// SAFETY: We check that nobody is actively writing now, but it is
12481267
// the caller's responsibility to ensure that nobody writes until
@@ -1406,7 +1425,8 @@ struct BorrowRef<'b> {
14061425

14071426
impl<'b> BorrowRef<'b> {
14081427
#[inline]
1409-
fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
1428+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1429+
const fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
14101430
let b = borrow.get().wrapping_add(1);
14111431
if !is_reading(b) {
14121432
// Incrementing borrow can result in a non-reading value (<= 0) in these cases:
@@ -1423,33 +1443,41 @@ impl<'b> BorrowRef<'b> {
14231443
// 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
14241444
// 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
14251445
// is large enough to represent having one more read borrow
1426-
borrow.set(b);
1446+
borrow.replace(b);
14271447
Some(BorrowRef { borrow })
14281448
}
14291449
}
1450+
1451+
/// FIXME(const-hack): `Clone` is not a `const_trait`, so work around that by making our own method
1452+
#[inline]
1453+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1454+
const fn clone(&self) -> Self {
1455+
// Since this Ref exists, we know the borrow flag
1456+
// is a reading borrow.
1457+
let borrow = self.borrow.get();
1458+
debug_assert!(is_reading(borrow));
1459+
// Prevent the borrow counter from overflowing into
1460+
// a writing borrow.
1461+
assert!(borrow != BorrowFlag::MAX);
1462+
self.borrow.replace(borrow + 1);
1463+
BorrowRef { borrow: self.borrow }
1464+
}
14301465
}
14311466

1432-
impl Drop for BorrowRef<'_> {
1467+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1468+
impl const Drop for BorrowRef<'_> {
14331469
#[inline]
14341470
fn drop(&mut self) {
14351471
let borrow = self.borrow.get();
14361472
debug_assert!(is_reading(borrow));
1437-
self.borrow.set(borrow - 1);
1473+
self.borrow.replace(borrow - 1);
14381474
}
14391475
}
14401476

14411477
impl Clone for BorrowRef<'_> {
14421478
#[inline]
14431479
fn clone(&self) -> Self {
1444-
// Since this Ref exists, we know the borrow flag
1445-
// is a reading borrow.
1446-
let borrow = self.borrow.get();
1447-
debug_assert!(is_reading(borrow));
1448-
// Prevent the borrow counter from overflowing into
1449-
// a writing borrow.
1450-
assert!(borrow != BorrowFlag::MAX);
1451-
self.borrow.set(borrow + 1);
1452-
BorrowRef { borrow: self.borrow }
1480+
self.clone()
14531481
}
14541482
}
14551483

@@ -1469,7 +1497,8 @@ pub struct Ref<'b, T: ?Sized + 'b> {
14691497
}
14701498

14711499
#[stable(feature = "rust1", since = "1.0.0")]
1472-
impl<T: ?Sized> Deref for Ref<'_, T> {
1500+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
1501+
impl<T: ?Sized> const Deref for Ref<'_, T> {
14731502
type Target = T;
14741503

14751504
#[inline]
@@ -1494,7 +1523,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
14941523
#[stable(feature = "cell_extras", since = "1.15.0")]
14951524
#[must_use]
14961525
#[inline]
1497-
pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
1526+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1527+
pub const fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
14981528
Ref { value: orig.value, borrow: orig.borrow.clone() }
14991529
}
15001530

@@ -1616,7 +1646,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
16161646
/// assert!(cell.try_borrow_mut().is_err());
16171647
/// ```
16181648
#[unstable(feature = "cell_leak", issue = "69099")]
1619-
pub fn leak(orig: Ref<'b, T>) -> &'b T {
1649+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1650+
pub const fn leak(orig: Ref<'b, T>) -> &'b T {
16201651
// By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
16211652
// UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
16221653
// unique reference to the borrowed RefCell. No further mutable references can be created
@@ -1782,7 +1813,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
17821813
/// assert!(cell.try_borrow_mut().is_err());
17831814
/// ```
17841815
#[unstable(feature = "cell_leak", issue = "69099")]
1785-
pub fn leak(mut orig: RefMut<'b, T>) -> &'b mut T {
1816+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1817+
pub const fn leak(mut orig: RefMut<'b, T>) -> &'b mut T {
17861818
// By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
17871819
// go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
17881820
// require a unique reference to the borrowed RefCell. No further references can be created
@@ -1798,25 +1830,27 @@ struct BorrowRefMut<'b> {
17981830
borrow: &'b Cell<BorrowFlag>,
17991831
}
18001832

1801-
impl Drop for BorrowRefMut<'_> {
1833+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1834+
impl const Drop for BorrowRefMut<'_> {
18021835
#[inline]
18031836
fn drop(&mut self) {
18041837
let borrow = self.borrow.get();
18051838
debug_assert!(is_writing(borrow));
1806-
self.borrow.set(borrow + 1);
1839+
self.borrow.replace(borrow + 1);
18071840
}
18081841
}
18091842

18101843
impl<'b> BorrowRefMut<'b> {
18111844
#[inline]
1812-
fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
1845+
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
1846+
const fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
18131847
// NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
18141848
// mutable reference, and so there must currently be no existing
18151849
// references. Thus, while clone increments the mutable refcount, here
18161850
// we explicitly only allow going from UNUSED to UNUSED - 1.
18171851
match borrow.get() {
18181852
UNUSED => {
1819-
borrow.set(UNUSED - 1);
1853+
borrow.replace(UNUSED - 1);
18201854
Some(BorrowRefMut { borrow })
18211855
}
18221856
_ => None,
@@ -1855,7 +1889,8 @@ pub struct RefMut<'b, T: ?Sized + 'b> {
18551889
}
18561890

18571891
#[stable(feature = "rust1", since = "1.0.0")]
1858-
impl<T: ?Sized> Deref for RefMut<'_, T> {
1892+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
1893+
impl<T: ?Sized> const Deref for RefMut<'_, T> {
18591894
type Target = T;
18601895

18611896
#[inline]
@@ -1866,7 +1901,8 @@ impl<T: ?Sized> Deref for RefMut<'_, T> {
18661901
}
18671902

18681903
#[stable(feature = "rust1", since = "1.0.0")]
1869-
impl<T: ?Sized> DerefMut for RefMut<'_, T> {
1904+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
1905+
impl<T: ?Sized> const DerefMut for RefMut<'_, T> {
18701906
#[inline]
18711907
fn deref_mut(&mut self) -> &mut T {
18721908
// SAFETY: the value is accessible as long as we hold our borrow.

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
#![feature(cfg_target_has_atomic)]
142142
#![feature(cfg_target_has_atomic_equal_alignment)]
143143
#![feature(cfg_ub_checks)]
144+
#![feature(const_destruct)]
144145
#![feature(const_precise_live_drops)]
145146
#![feature(const_trait_impl)]
146147
#![feature(decl_macro)]

0 commit comments

Comments
 (0)