From 97b7170eef055e88feb6d5d7eace6c8c35acb7e2 Mon Sep 17 00:00:00 2001 From: ltdk Date: Thu, 16 Oct 2025 15:04:43 -0400 Subject: [PATCH 1/4] const Cell methods --- library/core/src/cell.rs | 21 +++++++++++++++++---- library/coretests/tests/lib.rs | 1 + library/coretests/tests/ptr.rs | 29 ++++++++++++++--------------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index aeac35e45a5d0..988c50795e299 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 c2dc3a99ab109..5c2522acb1362 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 e89f21271027a..7afbb1260f239 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); } From b145213ceead916028d84db38f19b4288c85ea15 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 18 Oct 2025 23:35:23 +0000 Subject: [PATCH 2/4] Parse `const unsafe trait` properly Previously, this was greedily stolen by the `fn` parsing logic. --- compiler/rustc_parse/src/parser/item.rs | 5 ++++- .../traits/const-traits/parse-const-unsafe-trait.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/const-traits/parse-const-unsafe-trait.rs diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aa03d5956cd23..6f0e3b81cf2a6 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2664,7 +2664,10 @@ impl<'a> Parser<'a> { // Rule out `unsafe extern {`. && !self.is_unsafe_foreign_mod() // Rule out `async gen {` and `async gen move {` - && !self.is_async_gen_block()) + && !self.is_async_gen_block() + // Rule out `const unsafe auto` and `const unsafe trait`. + && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait]) + ) }) // `extern ABI fn` || self.check_keyword_case(exp!(Extern), case) diff --git a/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs b/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs new file mode 100644 index 0000000000000..3d62405d9ae20 --- /dev/null +++ b/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs @@ -0,0 +1,13 @@ +// Test that `const unsafe trait` and `const unsafe auto trait` works. + +//@ check-pass + +#![feature(const_trait_impl)] +#![feature(auto_traits)] + +pub const unsafe trait Owo {} +const unsafe trait OwO {} +pub const unsafe auto trait UwU {} +const unsafe auto trait Uwu {} + +fn main() {} From a1e42f96f68dede87bda42e58c7c5373e0c5e9e0 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sat, 20 Sep 2025 23:01:48 +0000 Subject: [PATCH 3/4] Simplify new_local. --- compiler/rustc_mir_transform/src/patch.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index 2c535d011a0e2..015bae56cf57e 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -24,6 +24,8 @@ pub(crate) struct MirPatch<'tcx> { // Cached block for UnwindTerminate (with reason) terminate_block: Option<(BasicBlock, UnwindTerminateReason)>, body_span: Span, + /// The number of locals at the start of the transformation. New locals + /// get appended at the end. next_local: usize, /// The number of blocks at the start of the transformation. New blocks /// get appended at the end. @@ -176,8 +178,7 @@ impl<'tcx> MirPatch<'tcx> { span: Span, local_info: LocalInfo<'tcx>, ) -> Local { - let index = self.next_local; - self.next_local += 1; + let index = self.next_local + self.new_locals.len(); let mut new_decl = LocalDecl::new(ty, span); **new_decl.local_info.as_mut().unwrap_crate_local() = local_info; self.new_locals.push(new_decl); @@ -186,8 +187,7 @@ impl<'tcx> MirPatch<'tcx> { /// Queues the addition of a new temporary. pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { - let index = self.next_local; - self.next_local += 1; + let index = self.next_local + self.new_locals.len(); self.new_locals.push(LocalDecl::new(ty, span)); Local::new(index) } @@ -195,8 +195,8 @@ impl<'tcx> MirPatch<'tcx> { /// Returns the type of a local that's newly-added in the patch. pub(crate) fn local_ty(&self, local: Local) -> Ty<'tcx> { let local = local.as_usize(); - assert!(local < self.next_local); - let new_local_idx = self.new_locals.len() - (self.next_local - local); + assert!(local < self.next_local + self.new_locals.len()); + let new_local_idx = local - self.next_local; self.new_locals[new_local_idx].ty } From a3495e577c27e6e3cf9a5b6bba1a2375abdf4f20 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sun, 19 Oct 2025 02:44:41 -0400 Subject: [PATCH 4/4] Move const_drop_in_place test from ptr to manually_drop module --- library/coretests/tests/manually_drop.rs | 38 ++++++++++++++++++++++++ library/coretests/tests/ptr.rs | 38 ------------------------ 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/library/coretests/tests/manually_drop.rs b/library/coretests/tests/manually_drop.rs index bbf444471ad2a..1638c82b161b4 100644 --- a/library/coretests/tests/manually_drop.rs +++ b/library/coretests/tests/manually_drop.rs @@ -27,3 +27,41 @@ fn smoke() { drop(x); drop(y); } + +#[test] +fn const_drop_in_place() { + const COUNTER: usize = { + use core::cell::Cell; + + let counter = Cell::new(0); + + // only exists to make `Drop` indirect impl + #[allow(dead_code)] + struct Test<'a>(Dropped<'a>); + + struct Dropped<'a>(&'a Cell); + impl const Drop for Dropped<'_> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } + } + + 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.get() == 1); + unsafe { + ManuallyDrop::drop(&mut two); + } + assert!(counter.get() == 2); + unsafe { + ManuallyDrop::drop(&mut three); + } + counter.get() + }; + assert_eq!(COUNTER, 3); +} diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index 7afbb1260f239..0039a37779f61 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -1045,41 +1045,3 @@ fn test_ptr_default() { let default = PtrMutDefaultTest::default(); assert!(default.ptr.is_null()); } - -#[test] -fn test_const_drop_in_place() { - const COUNTER: usize = { - use core::cell::Cell; - - let counter = Cell::new(0); - - // only exists to make `Drop` indirect impl - #[allow(dead_code)] - struct Test<'a>(Dropped<'a>); - - struct Dropped<'a>(&'a Cell); - impl const Drop for Dropped<'_> { - fn drop(&mut self) { - self.0.set(self.0.get() + 1); - } - } - - 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.get() == 1); - unsafe { - ManuallyDrop::drop(&mut two); - } - assert!(counter.get() == 2); - unsafe { - ManuallyDrop::drop(&mut three); - } - counter.get() - }; - assert_eq!(COUNTER, 3); -}