diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index aeac35e45a5d..988c50795e29 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,7 +252,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::{PhantomData, Unsize}; +use crate::marker::{Destruct, PhantomData, Unsize}; use crate::mem::{self, ManuallyDrop}; use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::panic::const_panic; @@ -429,7 +429,11 @@ impl Cell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn set(&self, val: T) { + #[rustc_const_unstable(feature = "const_cell_traits", issue = "147787")] + pub const fn set(&self, val: T) + where + T: [const] Destruct, + { self.replace(val); } @@ -561,7 +565,12 @@ impl Cell { /// ``` #[inline] #[stable(feature = "cell_update", since = "1.88.0")] - pub fn update(&self, f: impl FnOnce(T) -> T) { + #[rustc_const_unstable(feature = "const_cell_traits", issue = "147787")] + pub const fn update(&self, f: impl [const] FnOnce(T) -> T) + where + // FIXME(const-hack): `Copy` should imply `const Destruct` + T: [const] Destruct, + { let old = self.get(); self.set(f(old)); } @@ -654,7 +663,11 @@ impl Cell { /// assert_eq!(c.into_inner(), 0); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] - pub fn take(&self) -> T { + #[rustc_const_unstable(feature = "const_cell_traits", issue = "147787")] + pub const fn take(&self) -> T + where + T: [const] Default, + { self.replace(Default::default()) } } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index c2dc3a99ab10..5c2522acb136 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -16,6 +16,7 @@ #![feature(char_internals)] #![feature(char_max_len)] #![feature(clone_to_uninit)] +#![feature(const_cell_traits)] #![feature(const_cmp)] #![feature(const_convert)] #![feature(const_destruct)] diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index e89f21271027..7afbb1260f23 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -1049,38 +1049,37 @@ fn test_ptr_default() { #[test] fn test_const_drop_in_place() { const COUNTER: usize = { - let mut counter = 0; - let counter_ptr = &raw mut counter; + use core::cell::Cell; + + let counter = Cell::new(0); // only exists to make `Drop` indirect impl #[allow(dead_code)] - struct Test(Dropped); + struct Test<'a>(Dropped<'a>); - struct Dropped(*mut usize); - impl const Drop for Dropped { + struct Dropped<'a>(&'a Cell); + impl const Drop for Dropped<'_> { fn drop(&mut self) { - unsafe { - *self.0 += 1; - } + self.0.set(self.0.get() + 1); } } - let mut one = ManuallyDrop::new(Test(Dropped(counter_ptr))); - let mut two = ManuallyDrop::new(Test(Dropped(counter_ptr))); - let mut three = ManuallyDrop::new(Test(Dropped(counter_ptr))); - assert!(counter == 0); + let mut one = ManuallyDrop::new(Test(Dropped(&counter))); + let mut two = ManuallyDrop::new(Test(Dropped(&counter))); + let mut three = ManuallyDrop::new(Test(Dropped(&counter))); + assert!(counter.get() == 0); unsafe { ManuallyDrop::drop(&mut one); } - assert!(counter == 1); + assert!(counter.get() == 1); unsafe { ManuallyDrop::drop(&mut two); } - assert!(counter == 2); + assert!(counter.get() == 2); unsafe { ManuallyDrop::drop(&mut three); } - counter + counter.get() }; assert_eq!(COUNTER, 3); }