From b410334dcc5900817d4946de3699cf5ad90c3a03 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 4 Sep 2025 17:52:39 +0200 Subject: [PATCH 1/6] What are those commit messages? rarw w yeet, compiler impls nyaaaaaaa fmt w --- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_data_structures/src/marker.rs | 37 +++++++++++++ .../src/hir_ty_lowering/bounds.rs | 4 +- compiler/rustc_session/src/options.rs | 2 +- .../src/traits/select/mod.rs | 31 +++++++++-- library/alloc/src/boxed.rs | 8 ++- library/alloc/src/lib.rs | 1 + library/alloctests/tests/lib.rs | 1 + library/core/src/cell.rs | 21 ++++---- library/core/src/marker.rs | 26 +++++++-- library/core/src/ops/unsize.rs | 54 +++++++++++++------ library/core/src/panic/unwind_safe.rs | 2 +- library/core/src/pin.rs | 4 +- library/core/src/pin/unsafe_pinned.rs | 8 +-- library/core/src/ptr/non_null.rs | 13 +++-- library/core/src/ptr/unique.rs | 9 ++-- library/coretests/tests/lib.rs | 1 + library/std/src/lib.rs | 1 + 18 files changed, 174 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 132f04b05100f..86df17f5ed9e1 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,6 +10,7 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] +#![cfg_attr(not(bootstrap), feature(move_trait))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 2be9ba292f976..b806bac07989e 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,4 +1,6 @@ use std::alloc::Allocator; +#[cfg(not(bootstrap))] +use std::marker::Move; use std::marker::PointeeSized; #[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ @@ -25,6 +27,7 @@ macro_rules! impls_dyn_send_neg { } // Consistent with `std` +#[cfg(bootstrap)] impls_dyn_send_neg!( [std::env::Args] [std::env::ArgsOs] @@ -40,6 +43,22 @@ impls_dyn_send_neg!( [std::io::StderrLock<'_>] ); +#[cfg(not(bootstrap))] +impls_dyn_send_neg!( + [std::env::Args] + [std::env::ArgsOs] + [*const T where T: ?Sized + ?Move + PointeeSized] + [*mut T where T: ?Sized + ?Move + PointeeSized] + [std::ptr::NonNull where T: ?Sized + ?Move + PointeeSized] + [std::rc::Rc where T: ?Sized + ?Move, A: Allocator] + [std::rc::Weak where T: ?Sized + ?Move, A: Allocator] + [std::sync::MutexGuard<'_, T> where T: ?Sized + ?Move] + [std::sync::RwLockReadGuard<'_, T> where T: ?Sized + ?Move] + [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized + ?Move] + [std::io::StdoutLock<'_>] + [std::io::StderrLock<'_>] +); + #[cfg(any( unix, target_os = "hermit", @@ -98,6 +117,7 @@ macro_rules! impls_dyn_sync_neg { } // Consistent with `std` +#[cfg(bootstrap)] impls_dyn_sync_neg!( [std::env::Args] [std::env::ArgsOs] @@ -114,6 +134,23 @@ impls_dyn_sync_neg!( [std::sync::mpsc::Sender where T] ); +#[cfg(not(bootstrap))] +impls_dyn_sync_neg!( + [std::env::Args] + [std::env::ArgsOs] + [*const T where T: ?Sized + ?Move + PointeeSized] + [*mut T where T: ?Sized + ?Move + PointeeSized] + [std::cell::Cell where T: ?Sized + ?Move ] + [std::cell::RefCell where T: ?Sized + ?Move ] + [std::cell::UnsafeCell where T: ?Sized + ?Move ] + [std::ptr::NonNull where T: ?Sized + ?Move + PointeeSized] + [std::rc::Rc where T: ?Sized + ?Move , A: Allocator] + [std::rc::Weak where T: ?Sized + ?Move , A: Allocator] + [std::cell::OnceCell where T] + [std::sync::mpsc::Receiver where T] + [std::sync::mpsc::Sender where T] +); + #[cfg(any( unix, target_os = "hermit", diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 7accab8df87c7..f20a7fd96dc33 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -232,7 +232,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Adds `experimental_default_bounds` bounds to the supertrait bounds. + /// Sets `experimental_default_bounds` to true on trait super bounds. pub(crate) fn add_default_super_traits( &self, trait_def_id: LocalDefId, @@ -243,8 +243,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias); - // Supertraits for auto trait are unsound according to the unstable book: - // https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits if self.tcx().trait_is_auto(trait_def_id.to_def_id()) { return; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6dd90546de1b0..b6971fbeee75a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2311,7 +2311,7 @@ options! { "Use WebAssembly error handling for wasm32-unknown-emscripten"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), - experimental_default_bounds: bool = (false, parse_bool, [TRACKED], + experimental_default_bounds: bool = (true, parse_bool, [TRACKED], "enable default bounds for experimental group of auto traits"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], "export symbols from executables, as if they were dynamic libraries"), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fb4f28412d428..139076daad6c8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -474,7 +474,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } else { let has_non_region_infer = stack.obligation.predicate.has_non_region_infer(); - if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) { + let is_default_auto_trait = self + .tcx() + .as_lang_item(stack.obligation.predicate.def_id()) + .is_some_and(|lang_item| matches!(lang_item, LangItem::DefaultTrait1)); + if let Some(candidate) = + self.winnow_candidates(has_non_region_infer, is_default_auto_trait, candidates) + { self.filter_reservation_impls(candidate) } else { Ok(None) @@ -1821,6 +1827,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn winnow_candidates( &mut self, has_non_region_infer: bool, + is_default_auto_trait: bool, mut candidates: Vec>, ) -> Option> { if candidates.len() == 1 { @@ -1828,8 +1835,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } // We prefer `Sized` candidates over everything. - let mut sized_candidates = - candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); + let mut sized_candidates = candidates.iter().filter(|c| { + matches!(c.candidate, SizedCandidate) + || (is_default_auto_trait + && matches!(c.candidate, AutoImplCandidate | ImplCandidate(..))) + }); if let Some(sized_candidate) = sized_candidates.next() { // There should only ever be a single sized candidate // as they would otherwise overlap. @@ -1874,6 +1884,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> { break; } + if is_default_auto_trait { + // Need to prefer alias-bound over env candidates. + let alias_bound = candidates + .iter() + .filter_map( + |c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }, + ) + .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); + match alias_bound { + Some(Some(index)) => return Some(ProjectionCandidate(index)), + Some(None) => {} + None => return None, + } + } + // The next highest priority is for non-global where-bounds. However, while we don't // prefer global where-clauses here, we do bail with ambiguity when encountering both // a global and a non-global where-clause. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 49ff768bed1b2..358f758cbc964 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2058,7 +2058,10 @@ unsafe impl PinCoerceUnsized for Box {} // Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) // would need a lot of codegen and interpreter adjustments. #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: ?Sized> DispatchFromDyn> for Box {} +impl + ?core::marker::Move, U: ?Sized + ?core::marker::Move> + DispatchFromDyn> for Box +{ +} #[stable(feature = "box_borrow", since = "1.1.0")] impl Borrow for Box { @@ -2160,3 +2163,6 @@ impl Error for Box { Error::provide(&**self, request); } } + +#[unstable(feature = "move_trait", issue = "none")] +unsafe impl core::marker::Move for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 87ad5b0ce30e6..0fa1c0f709b33 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -127,6 +127,7 @@ #![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(move_trait)] #![feature(panic_internals)] #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 49fb21ef5f3ac..d52da85c11b4d 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -12,6 +12,7 @@ #![feature(int_format_into)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] +#![feature(move_trait)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index aeac35e45a5d0..ea1b6c78042fd 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,9 +252,9 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::{PhantomData, Unsize}; use crate::mem::{self, ManuallyDrop}; use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; +use crate::marker::{Move, PhantomData, Unsize}; use crate::panic::const_panic; use crate::pin::PinCoerceUnsized; use crate::ptr::{self, NonNull}; @@ -310,7 +310,7 @@ pub use once::OnceCell; #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct Cell { +pub struct Cell { value: UnsafeCell, } @@ -323,7 +323,7 @@ unsafe impl Send for Cell where T: Send {} // having an explicit negative impl is nice for documentation purposes // and results in nicer error messages. #[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for Cell {} +impl !Sync for Cell {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cell { @@ -670,7 +670,7 @@ impl, U> CoerceUnsized> for Cell {} // `self: Cell<&Self>` won't work // `self: CellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U> DispatchFromDyn> for Cell {} +impl + ?Move, U: ?Move> DispatchFromDyn> for Cell {} impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` @@ -2273,12 +2273,12 @@ impl fmt::Display for RefMut<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct UnsafeCell { +pub struct UnsafeCell { value: T, } #[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for UnsafeCell {} +impl !Sync for UnsafeCell {} impl UnsafeCell { /// Constructs a new instance of `UnsafeCell` which will wrap the specified @@ -2543,7 +2543,7 @@ impl, U> CoerceUnsized> for UnsafeCell {} // `self: UnsafeCell<&Self>` won't work // `self: UnsafeCellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U> DispatchFromDyn> for UnsafeCell {} +impl + ?Move, U: ?Move> DispatchFromDyn> for UnsafeCell {} /// [`UnsafeCell`], but [`Sync`]. /// @@ -2561,7 +2561,7 @@ impl, U> DispatchFromDyn> for UnsafeCell #[repr(transparent)] #[rustc_diagnostic_item = "SyncUnsafeCell"] #[rustc_pub_transparent] -pub struct SyncUnsafeCell { +pub struct SyncUnsafeCell { value: UnsafeCell, } @@ -2651,7 +2651,10 @@ impl, U> CoerceUnsized> for SyncUnsafeCell // `self: SyncUnsafeCellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] -impl, U> DispatchFromDyn> for SyncUnsafeCell {} +impl + ?Move, U: ?Move> DispatchFromDyn> + for SyncUnsafeCell +{ +} #[allow(unused)] fn assert_coerce_unsized( diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4b767d8d62218..4ff5d7e8b763f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -236,7 +236,7 @@ pub trait PointeeSized { #[lang = "unsize"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Unsize: PointeeSized { +pub trait Unsize: PointeeSized { // Empty. } @@ -819,7 +819,7 @@ impl !Sync for *mut T {} /// [drop check]: Drop#drop-check #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct PhantomData; +pub struct PhantomData; #[stable(feature = "rust1", since = "1.0.0")] impl Hash for PhantomData { @@ -913,7 +913,7 @@ pub trait DiscriminantKind { pub unsafe auto trait Freeze {} #[unstable(feature = "freeze", issue = "121675")] -impl !Freeze for UnsafeCell {} +impl !Freeze for UnsafeCell {} marker_impls! { #[unstable(feature = "freeze", issue = "121675")] unsafe Freeze for @@ -933,7 +933,7 @@ marker_impls! { #[lang = "unsafe_unpin"] pub(crate) unsafe auto trait UnsafeUnpin {} -impl !UnsafeUnpin for UnsafePinned {} +impl !UnsafeUnpin for UnsafePinned {} unsafe impl UnsafeUnpin for PhantomData {} unsafe impl UnsafeUnpin for *const T {} unsafe impl UnsafeUnpin for *mut T {} @@ -1341,3 +1341,21 @@ pub macro CoercePointee($item:item) { pub trait CoercePointeeValidated { /* compiler built-in */ } + +/// Types that do not require a stable memory address, and so can be freely +/// `move`d. +#[lang = "default_trait1"] +#[rustc_unsafe_specialization_marker] +#[unstable(feature = "move_trait", issue = "none")] +pub unsafe auto trait Move { + // empty. +} +marker_impls! { + #[unstable(feature = "move_trait", issue = "none")] + unsafe Move for + {T: ?Sized + PointeeSized + ?Move} *const T, + {T: ?Sized + PointeeSized + ?Move} *mut T, + {T: ?Sized + PointeeSized + ?Move} &T, + {T: ?Sized + PointeeSized + ?Move} &mut T, + {T: ?Sized + PointeeSized + ?Move} PhantomData, +} diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index f0781ee01fd53..6ba0bd7fdd320 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -1,4 +1,4 @@ -use crate::marker::{PointeeSized, Unsize}; +use crate::marker::{Move, PointeeSized, Unsize}; /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. @@ -39,34 +39,46 @@ pub trait CoerceUnsized { // &mut T -> &mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> + for &'a mut T +{ +} // &mut T -> &U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {} +impl<'a, 'b: 'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a U> + for &'b mut T +{ +} // &mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {} // &mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*const U> + for &'a mut T +{ +} // &T -> &U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, 'b: 'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a U> + for &'b T +{ +} // &T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} // *mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} +impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} // *mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} +impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} +impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} /// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically /// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. @@ -116,19 +128,31 @@ impl, U: PointeeSized> CoerceUnsized<*const U> for * /// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] -pub trait DispatchFromDyn { +pub trait DispatchFromDyn { // Empty. } // &T -> &U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized + ?Move> DispatchFromDyn<&'a U> + for &'a T +{ +} // &mut T -> &mut U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized + ?Move> DispatchFromDyn<&'a mut U> + for &'a mut T +{ +} // *const T -> *const U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: PointeeSized> DispatchFromDyn<*const U> for *const T {} +impl, U: PointeeSized + ?Move> DispatchFromDyn<*const U> + for *const T +{ +} // *mut T -> *mut U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {} +impl, U: PointeeSized + ?Move> DispatchFromDyn<*mut U> + for *mut T +{ +} diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 722af55103839..72047f5c55d34 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -197,7 +197,7 @@ impl UnwindSafe for AssertUnwindSafe {} // only thing which doesn't implement it (which then transitively applies to // everything else). #[stable(feature = "catch_unwind", since = "1.9.0")] -impl !RefUnwindSafe for UnsafeCell {} +impl !RefUnwindSafe for UnsafeCell {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl RefUnwindSafe for AssertUnwindSafe {} diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 81c2dabf0d1d8..e28e142bb1c78 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1091,7 +1091,7 @@ pub use self::unsafe_pinned::UnsafePinned; #[repr(transparent)] #[rustc_pub_transparent] #[derive(Copy, Clone)] -pub struct Pin { +pub struct Pin { pointer: Ptr, } @@ -1821,7 +1821,7 @@ where impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn + PinCoerceUnsized, - U: PinCoerceUnsized, + U: PinCoerceUnsized + ?crate::marker::Move, { } diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs index ae03809b4581f..9fd419b7aa01f 100644 --- a/library/core/src/pin/unsafe_pinned.rs +++ b/library/core/src/pin/unsafe_pinned.rs @@ -1,5 +1,5 @@ use crate::cell::UnsafeCell; -use crate::marker::Unpin; +use crate::marker::{Move, Unpin}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::Pin; use crate::{fmt, ptr}; @@ -24,7 +24,7 @@ use crate::{fmt, ptr}; #[lang = "unsafe_pinned"] #[repr(transparent)] #[unstable(feature = "unsafe_pinned", issue = "125735")] -pub struct UnsafePinned { +pub struct UnsafePinned { value: UnsafeCell, } @@ -36,7 +36,7 @@ unsafe impl Sync for UnsafePinned {} /// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt /// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned. #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl !Unpin for UnsafePinned {} +impl !Unpin for UnsafePinned {} // `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since // we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes @@ -177,6 +177,6 @@ impl, U> CoerceUnsized> for UnsafePinned // FIXME(unsafe_pinned) this logic is copied from UnsafeCell, is it still sound? #[unstable(feature = "dispatch_from_dyn", issue = "none")] // #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl, U> DispatchFromDyn> for UnsafePinned {} +impl, U: ?Move> DispatchFromDyn> for UnsafePinned {} // FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned? diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index a762e969b52dc..138140305aee3 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1,3 +1,5 @@ +use core::marker::Move; + use crate::cmp::Ordering; use crate::marker::{Destruct, PointeeSized, Unsize}; use crate::mem::{MaybeUninit, SizedTypeProperties}; @@ -72,7 +74,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonNull"] -pub struct NonNull { +pub struct NonNull { // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to // this is banned by . pointer: *const T, @@ -81,12 +83,12 @@ pub struct NonNull { /// `NonNull` pointers are not `Send` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Send for NonNull {} +impl !Send for NonNull {} /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Sync for NonNull {} +impl !Sync for NonNull {} impl NonNull { /// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. @@ -1657,7 +1659,10 @@ impl Copy for NonNull {} impl CoerceUnsized> for NonNull where T: Unsize {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl DispatchFromDyn> for NonNull where T: Unsize {} +impl DispatchFromDyn> for NonNull where + T: Unsize +{ +} #[stable(feature = "pin", since = "1.33.0")] unsafe impl PinCoerceUnsized for NonNull {} diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index cdc8b6cc936df..554810540c0ac 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::marker::{PhantomData, PointeeSized, Unsize}; +use crate::marker::{Move, PhantomData, PointeeSized, Unsize}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::PinCoerceUnsized; use crate::ptr::NonNull; @@ -32,7 +32,7 @@ use crate::ptr::NonNull; )] #[doc(hidden)] #[repr(transparent)] -pub struct Unique { +pub struct Unique { pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary // for dropck to understand that we logically own a `T`. @@ -169,7 +169,10 @@ impl Copy for Unique {} impl CoerceUnsized> for Unique where T: Unsize {} #[unstable(feature = "ptr_internals", issue = "none")] -impl DispatchFromDyn> for Unique where T: Unsize {} +impl DispatchFromDyn> for Unique where + T: Unsize +{ +} #[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] unsafe impl PinCoerceUnsized for Unique {} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index c2dc3a99ab109..86eedc08b51dd 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -82,6 +82,7 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] +#![feature(move_trait)] #![feature(never_type)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 60c8f53a0cc40..de4f70fe41724 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -352,6 +352,7 @@ #![feature(lazy_get)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] +#![feature(move_trait)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] From 64fa06cb7e433419fddefa614f769c68d89e05f7 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Thu, 9 Oct 2025 16:34:55 +0300 Subject: [PATCH 2/6] Rename Move to Forget and small changes Remove Move impl for Box; Remove Move impl for PhantomData. --- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_data_structures/src/marker.rs | 34 +++++++++---------- library/alloc/src/boxed.rs | 5 +-- library/alloc/src/lib.rs | 2 +- library/alloctests/tests/lib.rs | 2 +- library/core/src/cell.rs | 18 +++++----- library/core/src/marker.rs | 25 +++++++------- library/core/src/ops/unsize.rs | 35 +++++++++++--------- library/core/src/panic/unwind_safe.rs | 2 +- library/core/src/pin.rs | 4 +-- library/core/src/pin/unsafe_pinned.rs | 8 ++--- library/core/src/ptr/non_null.rs | 10 +++--- library/core/src/ptr/unique.rs | 6 ++-- library/coretests/tests/lib.rs | 2 +- library/std/src/lib.rs | 2 +- 15 files changed, 78 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 86df17f5ed9e1..cf56d6c9b59e5 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,7 +10,7 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(not(bootstrap), feature(move_trait))] +#![cfg_attr(not(bootstrap), feature(forget_trait))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index b806bac07989e..8e4345e9053c5 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,6 +1,6 @@ use std::alloc::Allocator; #[cfg(not(bootstrap))] -use std::marker::Move; +use std::marker::Forget; use std::marker::PointeeSized; #[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ @@ -47,14 +47,14 @@ impls_dyn_send_neg!( impls_dyn_send_neg!( [std::env::Args] [std::env::ArgsOs] - [*const T where T: ?Sized + ?Move + PointeeSized] - [*mut T where T: ?Sized + ?Move + PointeeSized] - [std::ptr::NonNull where T: ?Sized + ?Move + PointeeSized] - [std::rc::Rc where T: ?Sized + ?Move, A: Allocator] - [std::rc::Weak where T: ?Sized + ?Move, A: Allocator] - [std::sync::MutexGuard<'_, T> where T: ?Sized + ?Move] - [std::sync::RwLockReadGuard<'_, T> where T: ?Sized + ?Move] - [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized + ?Move] + [*const T where T: ?Sized + ?Forget + PointeeSized] + [*mut T where T: ?Sized + ?Forget + PointeeSized] + [std::ptr::NonNull where T: ?Sized + ?Forget + PointeeSized] + [std::rc::Rc where T: ?Sized + ?Forget, A: Allocator] + [std::rc::Weak where T: ?Sized + ?Forget, A: Allocator] + [std::sync::MutexGuard<'_, T> where T: ?Sized + ?Forget] + [std::sync::RwLockReadGuard<'_, T> where T: ?Sized + ?Forget] + [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized + ?Forget] [std::io::StdoutLock<'_>] [std::io::StderrLock<'_>] ); @@ -138,14 +138,14 @@ impls_dyn_sync_neg!( impls_dyn_sync_neg!( [std::env::Args] [std::env::ArgsOs] - [*const T where T: ?Sized + ?Move + PointeeSized] - [*mut T where T: ?Sized + ?Move + PointeeSized] - [std::cell::Cell where T: ?Sized + ?Move ] - [std::cell::RefCell where T: ?Sized + ?Move ] - [std::cell::UnsafeCell where T: ?Sized + ?Move ] - [std::ptr::NonNull where T: ?Sized + ?Move + PointeeSized] - [std::rc::Rc where T: ?Sized + ?Move , A: Allocator] - [std::rc::Weak where T: ?Sized + ?Move , A: Allocator] + [*const T where T: ?Sized + ?Forget + PointeeSized] + [*mut T where T: ?Sized + ?Forget + PointeeSized] + [std::cell::Cell where T: ?Sized + ?Forget ] + [std::cell::RefCell where T: ?Sized + ?Forget ] + [std::cell::UnsafeCell where T: ?Sized + ?Forget ] + [std::ptr::NonNull where T: ?Sized + ?Forget + PointeeSized] + [std::rc::Rc where T: ?Sized + ?Forget , A: Allocator] + [std::rc::Weak where T: ?Sized + ?Forget , A: Allocator] [std::cell::OnceCell where T] [std::sync::mpsc::Receiver where T] [std::sync::mpsc::Sender where T] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 358f758cbc964..db6beb772054d 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2058,7 +2058,7 @@ unsafe impl PinCoerceUnsized for Box {} // Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) // would need a lot of codegen and interpreter adjustments. #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl + ?core::marker::Move, U: ?Sized + ?core::marker::Move> +impl + ?core::marker::Forget, U: ?Sized + ?core::marker::Forget> DispatchFromDyn> for Box { } @@ -2163,6 +2163,3 @@ impl Error for Box { Error::provide(&**self, request); } } - -#[unstable(feature = "move_trait", issue = "none")] -unsafe impl core::marker::Move for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 0fa1c0f709b33..97e22498a52a7 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -127,7 +127,7 @@ #![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] -#![feature(move_trait)] +#![feature(forget_trait)] #![feature(panic_internals)] #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index d52da85c11b4d..9dd46fe8e4375 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -12,7 +12,7 @@ #![feature(int_format_into)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] -#![feature(move_trait)] +#![feature(forget_trait)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index ea1b6c78042fd..3ed74dc70a5d7 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -254,7 +254,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; use crate::mem::{self, ManuallyDrop}; use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; -use crate::marker::{Move, PhantomData, Unsize}; +use crate::marker::{Forget, PhantomData, Unsize}; use crate::panic::const_panic; use crate::pin::PinCoerceUnsized; use crate::ptr::{self, NonNull}; @@ -310,7 +310,7 @@ pub use once::OnceCell; #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct Cell { +pub struct Cell { value: UnsafeCell, } @@ -323,7 +323,7 @@ unsafe impl Send for Cell where T: Send {} // having an explicit negative impl is nice for documentation purposes // and results in nicer error messages. #[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for Cell {} +impl !Sync for Cell {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cell { @@ -670,7 +670,7 @@ impl, U> CoerceUnsized> for Cell {} // `self: Cell<&Self>` won't work // `self: CellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl + ?Move, U: ?Move> DispatchFromDyn> for Cell {} +impl + ?Forget, U: ?Forget> DispatchFromDyn> for Cell {} impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` @@ -2273,12 +2273,12 @@ impl fmt::Display for RefMut<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct UnsafeCell { +pub struct UnsafeCell { value: T, } #[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for UnsafeCell {} +impl !Sync for UnsafeCell {} impl UnsafeCell { /// Constructs a new instance of `UnsafeCell` which will wrap the specified @@ -2543,7 +2543,7 @@ impl, U> CoerceUnsized> for UnsafeCell {} // `self: UnsafeCell<&Self>` won't work // `self: UnsafeCellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl + ?Move, U: ?Move> DispatchFromDyn> for UnsafeCell {} +impl + ?Forget, U: ?Forget> DispatchFromDyn> for UnsafeCell {} /// [`UnsafeCell`], but [`Sync`]. /// @@ -2561,7 +2561,7 @@ impl + ?Move, U: ?Move> DispatchFromDyn> for #[repr(transparent)] #[rustc_diagnostic_item = "SyncUnsafeCell"] #[rustc_pub_transparent] -pub struct SyncUnsafeCell { +pub struct SyncUnsafeCell { value: UnsafeCell, } @@ -2651,7 +2651,7 @@ impl, U> CoerceUnsized> for SyncUnsafeCell // `self: SyncUnsafeCellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] -impl + ?Move, U: ?Move> DispatchFromDyn> +impl + ?Forget, U: ?Forget> DispatchFromDyn> for SyncUnsafeCell { } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4ff5d7e8b763f..38a976d6565ee 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -236,7 +236,7 @@ pub trait PointeeSized { #[lang = "unsize"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Unsize: PointeeSized { +pub trait Unsize: PointeeSized { // Empty. } @@ -819,7 +819,7 @@ impl !Sync for *mut T {} /// [drop check]: Drop#drop-check #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct PhantomData; +pub struct PhantomData; #[stable(feature = "rust1", since = "1.0.0")] impl Hash for PhantomData { @@ -913,7 +913,7 @@ pub trait DiscriminantKind { pub unsafe auto trait Freeze {} #[unstable(feature = "freeze", issue = "121675")] -impl !Freeze for UnsafeCell {} +impl !Freeze for UnsafeCell {} marker_impls! { #[unstable(feature = "freeze", issue = "121675")] unsafe Freeze for @@ -933,7 +933,7 @@ marker_impls! { #[lang = "unsafe_unpin"] pub(crate) unsafe auto trait UnsafeUnpin {} -impl !UnsafeUnpin for UnsafePinned {} +impl !UnsafeUnpin for UnsafePinned {} unsafe impl UnsafeUnpin for PhantomData {} unsafe impl UnsafeUnpin for *const T {} unsafe impl UnsafeUnpin for *mut T {} @@ -1346,16 +1346,15 @@ pub trait CoercePointeeValidated { /// `move`d. #[lang = "default_trait1"] #[rustc_unsafe_specialization_marker] -#[unstable(feature = "move_trait", issue = "none")] -pub unsafe auto trait Move { +#[unstable(feature = "forget_trait", issue = "none")] +pub unsafe auto trait Forget { // empty. } marker_impls! { - #[unstable(feature = "move_trait", issue = "none")] - unsafe Move for - {T: ?Sized + PointeeSized + ?Move} *const T, - {T: ?Sized + PointeeSized + ?Move} *mut T, - {T: ?Sized + PointeeSized + ?Move} &T, - {T: ?Sized + PointeeSized + ?Move} &mut T, - {T: ?Sized + PointeeSized + ?Move} PhantomData, + #[unstable(feature = "forget_trait", issue = "none")] + unsafe Forget for + {T: ?Sized + ?Forget} *const T, + {T: ?Sized + ?Forget} *mut T, + {T: ?Sized + ?Forget} &T, + {T: ?Sized + ?Forget} &mut T, } diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index 6ba0bd7fdd320..bff8d2ccc5add 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -1,4 +1,4 @@ -use crate::marker::{Move, PointeeSized, Unsize}; +use crate::marker::{Forget, PointeeSized, Unsize}; /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. @@ -39,46 +39,49 @@ pub trait CoerceUnsized { // &mut T -> &mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> +impl<'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T { } // &mut T -> &U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, 'b: 'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a U> +impl<'a, 'b: 'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T { } // &mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized> CoerceUnsized<*mut U> + for &'a mut T +{ +} // &mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*const U> +impl<'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T { } // &T -> &U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, 'b: 'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a U> +impl<'a, 'b: 'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b T { } // &T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} +impl<'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} // *mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} +impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} // *mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} +impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} +impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} /// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically /// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. @@ -128,31 +131,31 @@ impl, U: PointeeSized> CoerceUnsized<*const /// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] -pub trait DispatchFromDyn { +pub trait DispatchFromDyn { // Empty. } // &T -> &U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized + ?Move> DispatchFromDyn<&'a U> +impl<'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized + ?Forget> DispatchFromDyn<&'a U> for &'a T { } // &mut T -> &mut U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized + ?Move> DispatchFromDyn<&'a mut U> - for &'a mut T +impl<'a, T: PointeeSized + ?Forget + Unsize, U: PointeeSized + ?Forget> + DispatchFromDyn<&'a mut U> for &'a mut T { } // *const T -> *const U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: PointeeSized + ?Move> DispatchFromDyn<*const U> +impl, U: PointeeSized + ?Forget> DispatchFromDyn<*const U> for *const T { } // *mut T -> *mut U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: PointeeSized + ?Move> DispatchFromDyn<*mut U> +impl, U: PointeeSized + ?Forget> DispatchFromDyn<*mut U> for *mut T { } diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 72047f5c55d34..7e0e5ef2bcbf8 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -197,7 +197,7 @@ impl UnwindSafe for AssertUnwindSafe {} // only thing which doesn't implement it (which then transitively applies to // everything else). #[stable(feature = "catch_unwind", since = "1.9.0")] -impl !RefUnwindSafe for UnsafeCell {} +impl !RefUnwindSafe for UnsafeCell {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl RefUnwindSafe for AssertUnwindSafe {} diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index e28e142bb1c78..10dbdfa1f4398 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1091,7 +1091,7 @@ pub use self::unsafe_pinned::UnsafePinned; #[repr(transparent)] #[rustc_pub_transparent] #[derive(Copy, Clone)] -pub struct Pin { +pub struct Pin { pointer: Ptr, } @@ -1821,7 +1821,7 @@ where impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn + PinCoerceUnsized, - U: PinCoerceUnsized + ?crate::marker::Move, + U: PinCoerceUnsized + ?crate::marker::Forget, { } diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs index 9fd419b7aa01f..687b3f2be104f 100644 --- a/library/core/src/pin/unsafe_pinned.rs +++ b/library/core/src/pin/unsafe_pinned.rs @@ -1,5 +1,5 @@ use crate::cell::UnsafeCell; -use crate::marker::{Move, Unpin}; +use crate::marker::{Forget, Unpin}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::Pin; use crate::{fmt, ptr}; @@ -24,7 +24,7 @@ use crate::{fmt, ptr}; #[lang = "unsafe_pinned"] #[repr(transparent)] #[unstable(feature = "unsafe_pinned", issue = "125735")] -pub struct UnsafePinned { +pub struct UnsafePinned { value: UnsafeCell, } @@ -36,7 +36,7 @@ unsafe impl Sync for UnsafePinned {} /// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt /// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned. #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl !Unpin for UnsafePinned {} +impl !Unpin for UnsafePinned {} // `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since // we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes @@ -177,6 +177,6 @@ impl, U> CoerceUnsized> for UnsafePinned // FIXME(unsafe_pinned) this logic is copied from UnsafeCell, is it still sound? #[unstable(feature = "dispatch_from_dyn", issue = "none")] // #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl, U: ?Move> DispatchFromDyn> for UnsafePinned {} +impl, U: ?Forget> DispatchFromDyn> for UnsafePinned {} // FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned? diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 138140305aee3..bfe2cdf69c6ee 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1,4 +1,4 @@ -use core::marker::Move; +use core::marker::Forget; use crate::cmp::Ordering; use crate::marker::{Destruct, PointeeSized, Unsize}; @@ -74,7 +74,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonNull"] -pub struct NonNull { +pub struct NonNull { // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to // this is banned by . pointer: *const T, @@ -83,12 +83,12 @@ pub struct NonNull { /// `NonNull` pointers are not `Send` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Send for NonNull {} +impl !Send for NonNull {} /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Sync for NonNull {} +impl !Sync for NonNull {} impl NonNull { /// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. @@ -1659,7 +1659,7 @@ impl Copy for NonNull {} impl CoerceUnsized> for NonNull where T: Unsize {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl DispatchFromDyn> for NonNull where +impl DispatchFromDyn> for NonNull where T: Unsize { } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 554810540c0ac..117696be148ed 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::marker::{Move, PhantomData, PointeeSized, Unsize}; +use crate::marker::{Forget, PhantomData, PointeeSized, Unsize}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::PinCoerceUnsized; use crate::ptr::NonNull; @@ -32,7 +32,7 @@ use crate::ptr::NonNull; )] #[doc(hidden)] #[repr(transparent)] -pub struct Unique { +pub struct Unique { pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary // for dropck to understand that we logically own a `T`. @@ -169,7 +169,7 @@ impl Copy for Unique {} impl CoerceUnsized> for Unique where T: Unsize {} #[unstable(feature = "ptr_internals", issue = "none")] -impl DispatchFromDyn> for Unique where +impl DispatchFromDyn> for Unique where T: Unsize { } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 86eedc08b51dd..bffbd930752fd 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -82,7 +82,7 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] -#![feature(move_trait)] +#![feature(forget_trait)] #![feature(never_type)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index de4f70fe41724..32a9297045176 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -352,7 +352,7 @@ #![feature(lazy_get)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] -#![feature(move_trait)] +#![feature(forget_trait)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] From 12c54da867fc743138fabd4c626fa7fc933b7c32 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Tue, 23 Dec 2025 00:59:53 +0300 Subject: [PATCH 3/6] Add PhantomUnforget --- library/alloc/src/boxed.rs | 5 +---- library/core/src/cell.rs | 2 +- library/core/src/clone.rs | 4 ++-- library/core/src/default.rs | 3 ++- library/core/src/fmt/mod.rs | 4 ++-- library/core/src/lib.rs | 1 + library/core/src/marker.rs | 41 +++++++++++++++++++++++++++++++---- library/core/src/ops/deref.rs | 14 ++++++------ 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index db6beb772054d..49ff768bed1b2 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2058,10 +2058,7 @@ unsafe impl PinCoerceUnsized for Box {} // Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) // would need a lot of codegen and interpreter adjustments. #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl + ?core::marker::Forget, U: ?Sized + ?core::marker::Forget> - DispatchFromDyn> for Box -{ -} +impl, U: ?Sized> DispatchFromDyn> for Box {} #[stable(feature = "box_borrow", since = "1.1.0")] impl Borrow for Box { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 3ed74dc70a5d7..254415d8fb44e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,9 +252,9 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; +use crate::marker::{Forget, PhantomData, Unsize}; use crate::mem::{self, ManuallyDrop}; use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; -use crate::marker::{Forget, PhantomData, Unsize}; use crate::panic::const_panic; use crate::pin::PinCoerceUnsized; use crate::ptr::{self, NonNull}; diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 06d2c93cc698f..8d7412d1b2231 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -36,7 +36,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::marker::{Destruct, PointeeSized}; +use crate::marker::{Destruct, Forget, PointeeSized}; mod uninit; @@ -191,7 +191,7 @@ mod uninit; #[rustc_diagnostic_item = "Clone"] #[rustc_trivial_field_reads] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] -pub const trait Clone: Sized { +pub const trait Clone: Sized + ?Forget { /// Returns a duplicate of the value. /// /// Note that what "duplicate" means varies by type: diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 1cc4fb6e8fdd3..c26ad387c5fc5 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -3,6 +3,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::ascii::Char as AsciiChar; +use crate::marker::Forget; /// A trait for giving a type a useful default value. /// @@ -104,7 +105,7 @@ use crate::ascii::Char as AsciiChar; #[rustc_diagnostic_item = "Default"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] -pub const trait Default: Sized { +pub const trait Default: Sized + ?Forget { /// Returns the "default value" for a type. /// /// Default values are often some kind of initial value, identity value, or anything else that diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 0f255e57fe585..4b12d3355ba10 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -4,7 +4,7 @@ use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell}; use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8}; -use crate::marker::{PhantomData, PointeeSized}; +use crate::marker::{Forget, PhantomData, PointeeSized}; use crate::num::fmt as numfmt; use crate::ops::Deref; use crate::{iter, result, str}; @@ -870,7 +870,7 @@ impl Display for Arguments<'_> { #[doc(alias = "{:?}")] #[rustc_diagnostic_item = "Debug"] #[rustc_trivial_field_reads] -pub trait Debug: PointeeSized { +pub trait Debug: PointeeSized + ?Forget { #[doc = include_str!("fmt_trait_method_doc.md")] /// /// # Examples diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 54adf97f10020..644d993417780 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -114,6 +114,7 @@ #![feature(is_ascii_octdigit)] #![feature(lazy_get)] #![feature(link_cfg)] +#![feature(more_maybe_bounds)] #![feature(offset_of_enum)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 38a976d6565ee..7c4749e3895f9 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -175,7 +175,7 @@ pub trait Sized: MetaSized { // `MetaSized` being coinductive, despite having supertraits, is okay for the same reasons as // `Sized` above. #[rustc_coinductive] -pub trait MetaSized: PointeeSized { +pub trait MetaSized: PointeeSized + ?Forget { // Empty } @@ -191,7 +191,7 @@ pub trait MetaSized: PointeeSized { #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] #[rustc_coinductive] -pub trait PointeeSized { +pub trait PointeeSized: ?Forget { // Empty } @@ -462,7 +462,7 @@ marker_impls! { // library, and there's no way to safely have this behavior right now. #[rustc_unsafe_specialization_marker] #[rustc_diagnostic_item = "Copy"] -pub trait Copy: Clone { +pub trait Copy: Clone + ?Forget { // Empty. } @@ -1343,7 +1343,7 @@ pub trait CoercePointeeValidated { } /// Types that do not require a stable memory address, and so can be freely -/// `move`d. +/// forgotten using [`core::mem::forget`]. #[lang = "default_trait1"] #[rustc_unsafe_specialization_marker] #[unstable(feature = "forget_trait", issue = "none")] @@ -1358,3 +1358,36 @@ marker_impls! { {T: ?Sized + ?Forget} &T, {T: ?Sized + ?Forget} &mut T, } + +/// A marker type which does not implement `Forget`. +/// +/// If a type contains a `PhantomUnforget`, it will not implement `Forget` by default. +#[unstable(feature = "forget_trait", issue = "none")] +pub struct PhantomUnforget; + +#[unstable(feature = "forget_trait", issue = "none")] +impl Debug for PhantomUnforget { + fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { + f.debug_struct("PhantomUnforget").finish() + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl !Forget for PhantomUnforget {} + +#[unstable(feature = "forget_trait", issue = "none")] +impl Default for PhantomUnforget { + fn default() -> Self { + PhantomUnforget + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl Clone for PhantomUnforget { + fn clone(&self) -> Self { + PhantomUnforget + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl Copy for PhantomUnforget {} diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 305861ea7b698..b20e818cf9fc6 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -1,4 +1,4 @@ -use crate::marker::PointeeSized; +use crate::marker::{Forget, PointeeSized}; /// Used for immutable dereferencing operations, like `*v`. /// @@ -366,16 +366,16 @@ unsafe impl DerefPure for &mut T {} /// ``` #[lang = "receiver"] #[unstable(feature = "arbitrary_self_types", issue = "44874")] -pub trait Receiver: PointeeSized { +pub trait Receiver: PointeeSized + ?Forget { /// The target type on which the method may be called. #[rustc_diagnostic_item = "receiver_target"] #[lang = "receiver_target"] #[unstable(feature = "arbitrary_self_types", issue = "44874")] - type Target: ?Sized; + type Target: ?Sized + ?Forget; } #[unstable(feature = "arbitrary_self_types", issue = "44874")] -impl Receiver for P +impl Receiver for P where P: Deref, { @@ -393,12 +393,12 @@ where #[lang = "legacy_receiver"] #[unstable(feature = "legacy_receiver_trait", issue = "none")] #[doc(hidden)] -pub trait LegacyReceiver: PointeeSized { +pub trait LegacyReceiver: PointeeSized + ?Forget { // Empty. } #[unstable(feature = "legacy_receiver_trait", issue = "none")] -impl LegacyReceiver for &T {} +impl LegacyReceiver for &T {} #[unstable(feature = "legacy_receiver_trait", issue = "none")] -impl LegacyReceiver for &mut T {} +impl LegacyReceiver for &mut T {} From af597ceee3ea88adad7d21b19526e484d89ad73c Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Tue, 23 Dec 2025 14:08:23 +0300 Subject: [PATCH 4/6] Add new methods to ManuallyDrop, MaybeUninit, etc. --- .../rustc_hir_analysis/src/check/intrinsic.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 + library/core/src/any.rs | 3 +- library/core/src/clone.rs | 10 +- library/core/src/cmp.rs | 6 +- library/core/src/fmt/mod.rs | 18 +- library/core/src/intrinsics/mod.rs | 12 +- library/core/src/marker.rs | 14 +- library/core/src/mem/manually_drop.rs | 22 +- library/core/src/mem/maybe_uninit.rs | 394 ++++++++++-------- library/core/src/mem/mod.rs | 30 +- library/core/src/ptr/const_ptr.rs | 23 +- library/core/src/ptr/metadata.rs | 6 +- 13 files changed, 311 insertions(+), 229 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index bc3448be5823e..03eed5d58e6a2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -129,7 +129,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::fmuladdf32 | sym::fmuladdf64 | sym::fmuladdf128 - | sym::forget | sym::frem_algebraic | sym::fsub_algebraic | sym::is_val_statically_known diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ef72c478951b8..d0d371f4a2166 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -240,6 +240,7 @@ symbols! { Fn, FnMut, FnOnce, + Forget, Formatter, Forward, From, diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 3ab95438c3ff3..ebc45805924e6 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -86,6 +86,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::marker::Forget; use crate::{fmt, hash, intrinsics}; /////////////////////////////////////////////////////////////////////////////// @@ -854,7 +855,7 @@ impl fmt::Debug for TypeId { #[must_use] #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] -pub const fn type_name() -> &'static str { +pub const fn type_name() -> &'static str { const { intrinsics::type_name::() } } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 8d7412d1b2231..d9ca0d8374d3c 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -569,7 +569,7 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr { /// are implemented in `traits::SelectionContext::copy_clone_conditions()` /// in `rustc_trait_selection`. mod impls { - use crate::marker::PointeeSized; + use crate::marker::{Forget, PointeeSized}; macro_rules! impl_clone { ($($t:ty)*) => { @@ -604,7 +604,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] - impl const Clone for *const T { + impl const Clone for *const T { #[inline(always)] fn clone(&self) -> Self { *self @@ -613,7 +613,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] - impl const Clone for *mut T { + impl const Clone for *mut T { #[inline(always)] fn clone(&self) -> Self { *self @@ -623,7 +623,7 @@ mod impls { /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] - impl const Clone for &T { + impl const Clone for &T { #[inline(always)] #[rustc_diagnostic_item = "noop_method_clone"] fn clone(&self) -> Self { @@ -633,5 +633,5 @@ mod impls { /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] - impl !Clone for &mut T {} + impl !Clone for &mut T {} } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 7f369d19c3d12..5901af36bf86f 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -29,7 +29,7 @@ mod bytewise; pub(crate) use bytewise::BytewiseEq; use self::Ordering::*; -use crate::marker::{Destruct, PointeeSized}; +use crate::marker::{Destruct, Forget, PointeeSized}; use crate::ops::ControlFlow; /// Trait for comparisons using the equality operator. @@ -248,7 +248,9 @@ use crate::ops::ControlFlow; )] #[rustc_diagnostic_item = "PartialEq"] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -pub const trait PartialEq: PointeeSized { +pub const trait PartialEq: + PointeeSized + ?Forget +{ /// Tests for `self` and `other` values to be equal, and is used by `==`. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 4b12d3355ba10..e419de4250b38 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2655,11 +2655,11 @@ macro_rules! fmt_refs { ($($tr:ident),*) => { $( #[stable(feature = "rust1", since = "1.0.0")] - impl $tr for &T { + impl $tr for &T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] - impl $tr for &mut T { + impl $tr for &mut T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) } } )* @@ -2781,7 +2781,7 @@ impl Display for char { } #[stable(feature = "rust1", since = "1.0.0")] -impl Pointer for *const T { +impl Pointer for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { if <::Metadata as core::unit::IsUnit>::is_unit() { pointer_fmt_inner(self.expose_provenance(), f) @@ -2826,21 +2826,21 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul } #[stable(feature = "rust1", since = "1.0.0")] -impl Pointer for *mut T { +impl Pointer for *mut T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(&(*self as *const T), f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Pointer for &T { +impl Pointer for &T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(&(*self as *const T), f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Pointer for &mut T { +impl Pointer for &mut T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(&(&**self as *const T), f) } @@ -2849,13 +2849,13 @@ impl Pointer for &mut T { // Implementation of Display/Debug for various core types #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for *const T { +impl Debug for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for *mut T { +impl Debug for *mut T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(self, f) } @@ -2919,7 +2919,7 @@ impl Debug for () { } } #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for PhantomData { +impl Debug for PhantomData { fn fmt(&self, f: &mut Formatter<'_>) -> Result { write!(f, "PhantomData<{}>", crate::any::type_name::()) } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index cef700be9ea1f..200be1aaa17c8 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -55,7 +55,7 @@ #![allow(missing_docs)] use crate::ffi::va_list::{VaArgSafe, VaListImpl}; -use crate::marker::{ConstParamTy, DiscriminantKind, PointeeSized, Tuple}; +use crate::marker::{ConstParamTy, DiscriminantKind, Forget, PointeeSized, Tuple}; use crate::ptr; mod bounds; @@ -493,7 +493,7 @@ pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const fn assert_inhabited(); +pub const fn assert_inhabited(); /// A guard for unsafe functions that cannot ever be executed if `T` does not permit /// zero-initialization: This will statically either panic, or do nothing. It does not *guarantee* @@ -541,7 +541,7 @@ pub const fn caller_location() -> &'static crate::panic::Location<'static>; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const fn forget(_: T); +pub const unsafe fn forget(_: T); /// Reinterprets the bits of a value of one type as another type. /// @@ -2807,7 +2807,7 @@ pub const unsafe fn align_of_val(ptr: *const T) -> usize; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -pub const fn type_name() -> &'static str; +pub const fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever @@ -2857,7 +2857,9 @@ where #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn ptr_metadata + PointeeSized, M>(ptr: *const P) -> M; +pub const fn ptr_metadata + PointeeSized + ?Forget, M>( + ptr: *const P, +) -> M; /// This is an accidentally-stable alias to [`ptr::copy_nonoverlapping`]; use that instead. // Note (intentionally not in the doc comment): `ptr::copy_nonoverlapping` adds some extra diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 7c4749e3895f9..4c6089e256610 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -258,7 +258,7 @@ pub trait Unsize: PointeeSized { #[unstable(feature = "structural_match", issue = "31434")] #[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] #[lang = "structural_peq"] -pub trait StructuralPartialEq { +pub trait StructuralPartialEq: ?Forget { // Empty. } @@ -486,8 +486,8 @@ marker_impls! { isize, i8, i16, i32, i64, i128, f16, f32, f64, f128, bool, char, - {T: PointeeSized} *const T, - {T: PointeeSized} *mut T, + {T: PointeeSized + ?Forget} *const T, + {T: PointeeSized + ?Forget} *mut T, } @@ -496,7 +496,7 @@ impl Copy for ! {} /// Shared references can be copied, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] -impl Copy for &T {} +impl Copy for &T {} /// Marker trait for the types that are allowed in union fields and unsafe /// binder types. @@ -852,10 +852,10 @@ impl cmp::Ord for PhantomData { } #[stable(feature = "rust1", since = "1.0.0")] -impl Copy for PhantomData {} +impl Copy for PhantomData {} #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for PhantomData { +impl Clone for PhantomData { fn clone(&self) -> Self { Self } @@ -863,7 +863,7 @@ impl Clone for PhantomData { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] -impl const Default for PhantomData { +impl const Default for PhantomData { fn default() -> Self { Self } diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 334a4b7119a11..9043318677b7e 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -1,4 +1,4 @@ -use crate::marker::Destruct; +use crate::marker::{Destruct, Forget}; use crate::ops::{Deref, DerefMut, DerefPure}; use crate::ptr; @@ -155,7 +155,7 @@ use crate::ptr; #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] #[rustc_pub_transparent] -pub struct ManuallyDrop { +pub struct ManuallyDrop { value: T, } @@ -178,7 +178,10 @@ impl ManuallyDrop { #[stable(feature = "manually_drop", since = "1.20.0")] #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] - pub const fn new(value: T) -> ManuallyDrop { + pub const fn new(value: T) -> ManuallyDrop + where + T: Forget, + { ManuallyDrop { value } } @@ -225,6 +228,19 @@ impl ManuallyDrop { } } +impl ManuallyDrop { + /// Unchecked version of [`ManuallyDrop::new`] where `T` might not implement [`Forget`]. + /// + /// # Safety + /// + /// Caller must ensure `value` is dropped according to type's safety invariants. + #[unstable(feature = "forget_trait", issue = "none")] + #[inline(always)] + pub const unsafe fn new_unchecked(value: T) -> ManuallyDrop { + ManuallyDrop { value } + } +} + impl ManuallyDrop { /// Manually drops the contained value. /// diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 8d666e9b130c0..f6cd9887ffb65 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1,5 +1,5 @@ use crate::any::type_name; -use crate::marker::Destruct; +use crate::marker::{Destruct, Forget}; use crate::mem::ManuallyDrop; use crate::{fmt, intrinsics, ptr, slice}; @@ -259,13 +259,13 @@ use crate::{fmt, intrinsics, ptr, slice}; #[derive(Copy)] #[repr(transparent)] #[rustc_pub_transparent] -pub union MaybeUninit { +pub union MaybeUninit { uninit: (), value: ManuallyDrop, } #[stable(feature = "maybe_uninit", since = "1.36.0")] -impl Clone for MaybeUninit { +impl Clone for MaybeUninit { #[inline(always)] fn clone(&self) -> Self { // Not calling `T::clone()`, we cannot know if we are initialized enough for that. @@ -305,7 +305,10 @@ impl MaybeUninit { #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] #[must_use = "use `forget` to avoid running Drop code"] #[inline(always)] - pub const fn new(val: T) -> MaybeUninit { + pub const fn new(val: T) -> MaybeUninit + where + T: Forget, + { MaybeUninit { value: ManuallyDrop::new(val) } } @@ -472,94 +475,11 @@ impl MaybeUninit { #[inline(always)] #[stable(feature = "maybe_uninit_write", since = "1.55.0")] #[rustc_const_stable(feature = "const_maybe_uninit_write", since = "1.85.0")] - pub const fn write(&mut self, val: T) -> &mut T { - *self = MaybeUninit::new(val); - // SAFETY: We just initialized this value. - unsafe { self.assume_init_mut() } - } - - /// Gets a pointer to the contained value. Reading from this pointer or turning it - /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. - /// Writing to memory that this pointer (non-transitively) points to is undefined behavior - /// (except inside an `UnsafeCell`). - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>::uninit(); - /// x.write(vec![0, 1, 2]); - /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. - /// let x_vec = unsafe { &*x.as_ptr() }; - /// assert_eq!(x_vec.len(), 3); - /// # // Prevent leaks for Miri - /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::>::uninit(); - /// let x_vec = unsafe { &*x.as_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ - /// ``` - /// - /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] - #[rustc_as_ptr] - #[inline(always)] - pub const fn as_ptr(&self) -> *const T { - // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. - self as *const _ as *const T - } - - /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it - /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>::uninit(); - /// x.write(vec![0, 1, 2]); - /// // Create a reference into the `MaybeUninit>`. - /// // This is okay because we initialized it. - /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// x_vec.push(3); - /// assert_eq!(x_vec.len(), 4); - /// # // Prevent leaks for Miri - /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::>::uninit(); - /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ - /// ``` - /// - /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] - #[rustc_as_ptr] - #[inline(always)] - pub const fn as_mut_ptr(&mut self) -> *mut T { - // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. - self as *mut _ as *mut T + pub const fn write(&mut self, val: T) -> &mut T + where + T: Forget, + { + unsafe { self.write_unchecked(val) } } /// Extracts the value from the `MaybeUninit` container. This is a great way @@ -793,6 +713,132 @@ impl MaybeUninit { } } + /// Extracts the values from an array of `MaybeUninit` containers. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that all elements of the array are + /// in an initialized state. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_array_assume_init)] + /// use std::mem::MaybeUninit; + /// + /// let mut array: [MaybeUninit; 3] = [MaybeUninit::uninit(); 3]; + /// array[0].write(0); + /// array[1].write(1); + /// array[2].write(2); + /// + /// // SAFETY: Now safe as we initialised all elements + /// let array = unsafe { + /// MaybeUninit::array_assume_init(array) + /// }; + /// + /// assert_eq!(array, [0, 1, 2]); + /// ``` + #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")] + #[inline(always)] + #[track_caller] + pub const unsafe fn array_assume_init(array: [Self; N]) -> [T; N] { + // SAFETY: + // * The caller guarantees that all elements of the array are initialized + // * `MaybeUninit` and T are guaranteed to have the same layout + // * `MaybeUninit` does not drop, so there are no double-frees + // And thus the conversion is safe + unsafe { + intrinsics::assert_inhabited::<[T; N]>(); + intrinsics::transmute_unchecked(array) + } + } + + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let val = 0x12345678_i32; + /// let uninit = MaybeUninit::new(val); + /// let uninit_bytes = uninit.as_bytes(); + /// let bytes = unsafe { uninit_bytes.assume_init_ref() }; + /// assert_eq!(bytes, val.to_ne_bytes()); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub const fn as_bytes(&self) -> &[MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts(self.as_ptr().cast::>(), super::size_of::()) + } + } + + /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized + /// bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes)] + /// use std::mem::MaybeUninit; + /// + /// let val = 0x12345678_i32; + /// let mut uninit = MaybeUninit::new(val); + /// let uninit_bytes = uninit.as_bytes_mut(); + /// if cfg!(target_endian = "little") { + /// uninit_bytes[0].write(0xcd); + /// } else { + /// uninit_bytes[3].write(0xcd); + /// } + /// let val2 = unsafe { uninit.assume_init() }; + /// assert_eq!(val2, 0x123456cd); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().cast::>(), + super::size_of::(), + ) + } + } + + /// Gets a pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const fn slice_as_ptr(this: &[MaybeUninit]) -> *const T { + this.as_ptr() as *const T + } + + /// Gets a mutable pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit]) -> *mut T { + this.as_mut_ptr() as *mut T + } +} + +impl MaybeUninit { + /// Unchecked version of [`MaybeUninit::new`] where `T` might not implement [`Forget`]. + /// + /// # Safety + /// + /// Caller must ensure `val` is dropped according to type's safety invariants. + #[unstable(feature = "forget_trait", issue = "none")] + #[inline(always)] + pub const unsafe fn new_unchecked(val: T) -> MaybeUninit { + MaybeUninit { value: unsafe { ManuallyDrop::new_unchecked(val) } } + } + /// Gets a mutable (unique) reference to the contained value. /// /// This can be useful when we want to access a `MaybeUninit` that has been @@ -910,117 +956,103 @@ impl MaybeUninit { } } - /// Extracts the values from an array of `MaybeUninit` containers. + /// Unchecked version of [`MaybeUninit::write`] where `T` might not implement [`Forget`]. /// /// # Safety /// - /// It is up to the caller to guarantee that all elements of the array are - /// in an initialized state. + /// Caller must ensure `val` is dropped according to type's safety invariants. + #[inline(always)] + #[unstable(feature = "forget_trait", issue = "none")] + pub const unsafe fn write_unchecked(&mut self, val: T) -> &mut T { + // SAFETY: We just initialized this value. + unsafe { + *self = MaybeUninit::new_unchecked(val); + self.assume_init_mut() + } + } + + /// Gets a pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// Writing to memory that this pointer (non-transitively) points to is undefined behavior + /// (except inside an `UnsafeCell`). /// /// # Examples /// - /// ``` - /// #![feature(maybe_uninit_array_assume_init)] + /// Correct usage of this method: + /// + /// ```rust /// use std::mem::MaybeUninit; /// - /// let mut array: [MaybeUninit; 3] = [MaybeUninit::uninit(); 3]; - /// array[0].write(0); - /// array[1].write(1); - /// array[2].write(2); + /// let mut x = MaybeUninit::>::uninit(); + /// x.write(vec![0, 1, 2]); + /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. + /// let x_vec = unsafe { &*x.as_ptr() }; + /// assert_eq!(x_vec.len(), 3); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } + /// ``` /// - /// // SAFETY: Now safe as we initialised all elements - /// let array = unsafe { - /// MaybeUninit::array_assume_init(array) - /// }; + /// *Incorrect* usage of this method: /// - /// assert_eq!(array, [0, 1, 2]); + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &*x.as_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ /// ``` - #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")] + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] + #[rustc_as_ptr] #[inline(always)] - #[track_caller] - pub const unsafe fn array_assume_init(array: [Self; N]) -> [T; N] { - // SAFETY: - // * The caller guarantees that all elements of the array are initialized - // * `MaybeUninit` and T are guaranteed to have the same layout - // * `MaybeUninit` does not drop, so there are no double-frees - // And thus the conversion is safe - unsafe { - intrinsics::assert_inhabited::<[T; N]>(); - intrinsics::transmute_unchecked(array) - } + pub const fn as_ptr(&self) -> *const T { + // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. + self as *const _ as *const T } - /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. - /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. /// /// # Examples /// - /// ``` - /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] + /// Correct usage of this method: + /// + /// ```rust /// use std::mem::MaybeUninit; /// - /// let val = 0x12345678_i32; - /// let uninit = MaybeUninit::new(val); - /// let uninit_bytes = uninit.as_bytes(); - /// let bytes = unsafe { uninit_bytes.assume_init_ref() }; - /// assert_eq!(bytes, val.to_ne_bytes()); + /// let mut x = MaybeUninit::>::uninit(); + /// x.write(vec![0, 1, 2]); + /// // Create a reference into the `MaybeUninit>`. + /// // This is okay because we initialized it. + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// x_vec.push(3); + /// assert_eq!(x_vec.len(), 4); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } /// ``` - #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub const fn as_bytes(&self) -> &[MaybeUninit] { - // SAFETY: MaybeUninit is always valid, even for padding bytes - unsafe { - slice::from_raw_parts(self.as_ptr().cast::>(), super::size_of::()) - } - } - - /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized - /// bytes. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. - /// - /// # Examples + /// *Incorrect* usage of this method: /// - /// ``` - /// #![feature(maybe_uninit_as_bytes)] + /// ```rust,no_run /// use std::mem::MaybeUninit; /// - /// let val = 0x12345678_i32; - /// let mut uninit = MaybeUninit::new(val); - /// let uninit_bytes = uninit.as_bytes_mut(); - /// if cfg!(target_endian = "little") { - /// uninit_bytes[0].write(0xcd); - /// } else { - /// uninit_bytes[3].write(0xcd); - /// } - /// let val2 = unsafe { uninit.assume_init() }; - /// assert_eq!(val2, 0x123456cd); + /// let mut x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ /// ``` - #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit] { - // SAFETY: MaybeUninit is always valid, even for padding bytes - unsafe { - slice::from_raw_parts_mut( - self.as_mut_ptr().cast::>(), - super::size_of::(), - ) - } - } - - /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[inline(always)] - pub const fn slice_as_ptr(this: &[MaybeUninit]) -> *const T { - this.as_ptr() as *const T - } - - /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] + #[rustc_as_ptr] #[inline(always)] - pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit]) -> *mut T { - this.as_mut_ptr() as *mut T + pub const fn as_mut_ptr(&mut self) -> *mut T { + // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. + self as *mut _ as *mut T } } @@ -1071,7 +1103,7 @@ impl [MaybeUninit] { #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] pub const fn write_copy_of_slice(&mut self, src: &[T]) -> &mut [T] where - T: Copy, + T: Copy + Forget, { // SAFETY: &[T] and &[MaybeUninit] have the same layout let uninit_src: &[MaybeUninit] = unsafe { super::transmute(src) }; @@ -1134,7 +1166,7 @@ impl [MaybeUninit] { #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] pub fn write_clone_of_slice(&mut self, src: &[T]) -> &mut [T] where - T: Clone, + T: Clone + Forget, { // unlike copy_from_slice this does not call clone_from_slice on the slice // this is because `MaybeUninit` does not implement Clone. @@ -1188,7 +1220,7 @@ impl [MaybeUninit] { #[unstable(feature = "maybe_uninit_fill", issue = "117428")] pub fn write_filled(&mut self, value: T) -> &mut [T] where - T: Clone, + T: Clone + Forget, { SpecFill::spec_fill(self, value); // SAFETY: Valid elements have just been filled into `self` so it is initialized @@ -1222,6 +1254,7 @@ impl [MaybeUninit] { pub fn write_with(&mut self, mut f: F) -> &mut [T] where F: FnMut(usize) -> T, + T: Forget, { let mut guard = Guard { slice: self, initialized: 0 }; @@ -1298,6 +1331,7 @@ impl [MaybeUninit] { pub fn write_iter(&mut self, it: I) -> (&mut [T], &mut [MaybeUninit]) where I: IntoIterator, + T: Forget, { let iter = it.into_iter(); let mut guard = Guard { slice: self, initialized: 0 }; diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index c484551187cc3..6d9439e91a31f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -6,7 +6,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::alloc::Layout; -use crate::marker::DiscriminantKind; +use crate::marker::{DiscriminantKind, Forget}; use crate::panic::const_assert; use crate::{clone, cmp, fmt, hash, intrinsics, ptr}; @@ -148,10 +148,21 @@ pub use crate::intrinsics::transmute; #[rustc_const_stable(feature = "const_forget", since = "1.46.0")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "mem_forget"] -pub const fn forget(t: T) { +pub const fn forget(t: T) { let _ = ManuallyDrop::new(t); } +/// Unchecked version of [`forget`] where `T` might not implement [`Forget`]. +/// +/// # Safety +/// +/// Caller must ensure `t` is dropped according to type's safety invariants. +#[inline] +#[unstable(feature = "forget_trait", issue = "none")] +pub const unsafe fn forget_unchecked(t: T) { + let _ = unsafe { ManuallyDrop::new_unchecked(t) }; +} + /// Like [`forget`], but also accepts unsized values. /// /// While Rust does not permit unsized locals since its removal in [#111942] it is @@ -182,8 +193,19 @@ pub const fn forget(t: T) { /// [#71170]: https://github.com/rust-lang/rust/pull/71170 #[inline] #[unstable(feature = "forget_unsized", issue = "none")] -pub fn forget_unsized(t: T) { - intrinsics::forget(t) +pub fn forget_unsized(t: T) { + unsafe { forget_unsized_unchecked(t) } +} + +/// Unchecked version of [`forget_unsized`] where `T` might not implement [`Forget`]. +/// +/// # Safety +/// +/// Caller must ensure `t` is dropped according to type's safety invariants. +#[inline] +#[unstable(feature = "forget_trait", issue = "none")] +pub unsafe fn forget_unsized_unchecked(t: T) { + unsafe { intrinsics::forget(t) } } /// Returns the size of a type in bytes. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 451092709443b..85939e812a90b 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1,6 +1,7 @@ use super::*; use crate::cmp::Ordering::{Equal, Greater, Less}; use crate::intrinsics::const_eval_select; +use crate::marker::Forget; use crate::mem::{self, SizedTypeProperties}; use crate::slice::{self, SliceIndex}; @@ -40,15 +41,6 @@ impl *const T { ) } - /// Casts to a pointer of another type. - #[stable(feature = "ptr_cast", since = "1.38.0")] - #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] - #[rustc_diagnostic_item = "const_ptr_cast"] - #[inline(always)] - pub const fn cast(self) -> *const U { - self as _ - } - /// Try to cast to a pointer of another type by checking alignment. /// /// If the pointer is properly aligned to the target type, it will be @@ -158,6 +150,17 @@ impl *const T { // provenance). unsafe { mem::transmute(self.cast::<()>()) } } +} + +impl *const T { + /// Casts to a pointer of another type. + #[stable(feature = "ptr_cast", since = "1.38.0")] + #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] + #[rustc_diagnostic_item = "const_ptr_cast"] + #[inline(always)] + pub const fn cast(self) -> *const U { + self as _ + } /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in /// [`with_exposed_provenance`] and returns the "address" portion. @@ -186,7 +189,9 @@ impl *const T { pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } +} +impl *const T { /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of /// `self`. /// diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index dc3ec3fd19945..f3faa386355fe 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -3,7 +3,7 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata}; -use crate::marker::{Freeze, PointeeSized}; +use crate::marker::{Forget, Freeze, PointeeSized}; use crate::ptr::NonNull; /// Provides the pointer metadata type of any pointed-to type. @@ -55,7 +55,7 @@ use crate::ptr::NonNull; #[lang = "pointee_trait"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Pointee: PointeeSized { +pub trait Pointee: PointeeSized + ?Forget { /// The type for metadata in pointers and references to `Self`. #[lang = "metadata_type"] // NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata` @@ -96,7 +96,7 @@ pub trait Thin = Pointee + PointeeSized; /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` #[inline] -pub const fn metadata(ptr: *const T) -> ::Metadata { +pub const fn metadata(ptr: *const T) -> ::Metadata { ptr_metadata(ptr) } From 0c2bff4dc5dc05dbd1bf92f23915dcb57fa99d5c Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Tue, 23 Dec 2025 18:54:55 +0300 Subject: [PATCH 5/6] Add !Forget opt-out case with ForgetStatic --- library/core/src/cmp.rs | 30 ++-- library/core/src/convert/mod.rs | 8 +- library/core/src/intrinsics/mod.rs | 2 +- .../core/src/iter/sources/from_coroutine.rs | 6 +- library/core/src/marker.rs | 148 +++++++++++++++++- library/core/src/ops/coroutine.rs | 9 +- library/core/src/ops/deref.rs | 20 +-- library/core/src/ops/function.rs | 22 +-- library/core/src/option.rs | 6 +- library/core/src/pin.rs | 7 +- 10 files changed, 202 insertions(+), 56 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 5901af36bf86f..ec491b13e740b 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1353,8 +1353,8 @@ pub macro Ord($item:item) { #[rustc_diagnostic_item = "PartialOrd"] #[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -pub const trait PartialOrd: - [const] PartialEq + PointeeSized +pub const trait PartialOrd: + [const] PartialEq + PointeeSized + ?Forget { /// This method returns an ordering between `self` and `other` values if one exists. /// @@ -1502,8 +1502,8 @@ const fn default_chaining_impl( p: impl [const] FnOnce(Ordering) -> bool + [const] Destruct, ) -> ControlFlow where - T: [const] PartialOrd + PointeeSized, - U: PointeeSized, + T: [const] PartialOrd + PointeeSized + ?Forget, + U: PointeeSized + ?Forget, { // It's important that this only call `partial_cmp` once, not call `eq` then // one of the relational operators. We don't want to `bcmp`-then-`memcp` a @@ -1855,7 +1855,7 @@ where mod impls { use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::hint::unreachable_unchecked; - use crate::marker::PointeeSized; + use crate::marker::{Forget, PointeeSized}; use crate::ops::ControlFlow::{self, Break, Continue}; macro_rules! partial_eq_impl { @@ -2083,7 +2083,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const PartialEq<&B> for &A + impl const PartialEq<&B> for &A where A: [const] PartialEq, { @@ -2098,7 +2098,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const PartialOrd<&B> for &A + impl const PartialOrd<&B> for &A where A: [const] PartialOrd, { @@ -2141,7 +2141,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const Ord for &A + impl const Ord for &A where A: [const] Ord, { @@ -2152,13 +2152,13 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const Eq for &A where A: [const] Eq {} + impl const Eq for &A where A: [const] Eq {} // &mut pointers #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const PartialEq<&mut B> for &mut A + impl const PartialEq<&mut B> for &mut A where A: [const] PartialEq, { @@ -2173,7 +2173,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const PartialOrd<&mut B> for &mut A + impl const PartialOrd<&mut B> for &mut A where A: [const] PartialOrd, { @@ -2216,7 +2216,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const Ord for &mut A + impl const Ord for &mut A where A: [const] Ord, { @@ -2227,11 +2227,11 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const Eq for &mut A where A: [const] Eq {} + impl const Eq for &mut A where A: [const] Eq {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const PartialEq<&mut B> for &A + impl const PartialEq<&mut B> for &A where A: [const] PartialEq, { @@ -2247,7 +2247,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] - impl const PartialEq<&B> for &mut A + impl const PartialEq<&B> for &mut A where A: [const] PartialEq, { diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 89cda30c03036..e9bda3eae68bc 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -38,7 +38,7 @@ use crate::error::Error; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::marker::PointeeSized; +use crate::marker::{Forget, PointeeSized}; mod num; @@ -217,7 +217,7 @@ pub const fn identity(x: T) -> T { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "AsRef"] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -pub const trait AsRef: PointeeSized { +pub const trait AsRef: PointeeSized + ?Forget { /// Converts this type into a shared reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] fn as_ref(&self) -> &T; @@ -369,7 +369,7 @@ pub const trait AsRef: PointeeSized { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "AsMut"] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -pub const trait AsMut: PointeeSized { +pub const trait AsMut: PointeeSized + ?Forget { /// Converts this type into a mutable reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] fn as_mut(&mut self) -> &mut T; @@ -584,7 +584,7 @@ pub const trait Into: Sized { ))] #[doc(search_unbox)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -pub const trait From: Sized { +pub const trait From: Sized + ?Forget { /// Converts to this type from the input type. #[rustc_diagnostic_item = "from_fn"] #[must_use] diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 200be1aaa17c8..636a02a35aef4 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2191,7 +2191,7 @@ pub const unsafe fn write_via_move(ptr: *mut T, value: T); #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const fn discriminant_value(v: &T) -> ::Discriminant; +pub const fn discriminant_value(v: &T) -> ::Discriminant; /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs. diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs index 710ba504ded64..5d541eeab1396 100644 --- a/library/core/src/iter/sources/from_coroutine.rs +++ b/library/core/src/iter/sources/from_coroutine.rs @@ -1,4 +1,5 @@ use crate::fmt; +use crate::marker::Forget; use crate::ops::{Coroutine, CoroutineState}; use crate::pin::Pin; @@ -39,7 +40,10 @@ pub fn from_coroutine + Unpin>(coroutine: G) -> FromCo pub struct FromCoroutine(G); #[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")] -impl + Unpin> Iterator for FromCoroutine { +impl + Unpin> Iterator for FromCoroutine +where + G::Yield: Forget, +{ type Item = G::Yield; fn next(&mut self) -> Option { diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4c6089e256610..d39df4ec45be7 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -14,10 +14,11 @@ pub use self::variance::{ PhantomInvariant, PhantomInvariantLifetime, Variance, variance, }; use crate::cell::UnsafeCell; -use crate::cmp; use crate::fmt::Debug; use crate::hash::{Hash, Hasher}; -use crate::pin::UnsafePinned; +use crate::ops::{Coroutine, CoroutineState}; +use crate::pin::{Pin, UnsafePinned}; +use crate::{cmp, task}; // NOTE: for consistent error messages between `core` and `minicore`, all `diagnostic` attributes // should be replicated exactly in `minicore` (if `minicore` defines the item). @@ -870,7 +871,7 @@ impl const Default for PhantomData { } #[unstable(feature = "structural_match", issue = "31434")] -impl StructuralPartialEq for PhantomData {} +impl StructuralPartialEq for PhantomData {} /// Compiler-internal trait used to indicate the type of enum discriminants. /// @@ -887,7 +888,7 @@ impl StructuralPartialEq for PhantomData {} #[lang = "discriminant_kind"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait DiscriminantKind { +pub trait DiscriminantKind: ?Forget { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. #[lang = "discriminant_type"] @@ -1068,7 +1069,7 @@ pub const trait Destruct {} #[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Tuple {} +pub trait Tuple: ?Forget {} /// A marker for types which can be used as types of `const` generic parameters. /// @@ -1391,3 +1392,140 @@ impl Clone for PhantomUnforget { #[unstable(feature = "forget_trait", issue = "none")] impl Copy for PhantomUnforget {} + +/// A wrapper struct over `T: ?Forget + 'static` types which itself implements `Forget`. +#[unstable(feature = "forget_trait", issue = "none")] +#[derive(Default, Debug, Clone, Copy, Hash, Ord, Eq)] +pub struct ForgetStatic(T); + +#[unstable(feature = "forget_trait", issue = "none")] +unsafe impl Forget for ForgetStatic {} + +#[unstable(feature = "forget_trait", issue = "none")] +impl ForgetStatic { + /// Gets pinned exclusive access to the underlying value. + /// + /// `ForgetStatic` is considered to _structurally pin_ the underlying + /// value, which means _unpinned_ `ForgetStatic`s can produce _unpinned_ + /// access to the underlying value, but _pinned_ `ForgetStatic`s only + /// produce _pinned_ access to the underlying value. + #[unstable(feature = "forget_trait", issue = "none")] + #[must_use] + #[inline] + pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { + // SAFETY: `ForgetStatic` can only produce `&mut T` if itself is unpinned + // `Pin::map_unchecked_mut` is not const, so we do this conversion manually + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) } + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl From for ForgetStatic { + #[inline] + fn from(t: T) -> Self { + ForgetStatic(t) + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl FnOnce for ForgetStatic +where + F: FnOnce + ?Forget + 'static, + Args: Tuple + ?Forget, +{ + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + self.0.call_once(args) + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl FnMut for ForgetStatic +where + F: FnMut + ?Forget + 'static, + Args: Tuple + ?Forget, +{ + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + self.0.call_mut(args) + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl Fn for ForgetStatic +where + F: Fn + ?Forget + 'static, + Args: Tuple + ?Forget, +{ + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + self.0.call(args) + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl Future for ForgetStatic +where + T: Future + ?Sized + ?Forget + 'static, +{ + type Output = T::Output; + + #[inline] + fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll { + self.get_pin_mut().poll(cx) + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl Coroutine for ForgetStatic +where + G: Coroutine + ?Sized + ?Forget + 'static, +{ + type Yield = G::Yield; + type Return = G::Return; + + #[inline] + fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState { + G::resume(self.get_pin_mut(), arg) + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl AsRef for ForgetStatic +where + T: ?Sized + ?Forget + 'static, +{ + #[inline] + fn as_ref(&self) -> &T { + &self.0 + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl PartialEq> for ForgetStatic +where + T: PartialEq + ?Sized + ?Forget + 'static, + U: ?Sized + ?Forget + 'static, +{ + #[inline] + fn eq(&self, other: &ForgetStatic) -> bool { + self.0 == other.0 + } +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl StructuralPartialEq for ForgetStatic where + T: StructuralPartialEq + ?Sized + ?Forget + 'static +{ +} + +#[unstable(feature = "forget_trait", issue = "none")] +impl PartialOrd> for ForgetStatic +where + T: PartialOrd + ?Sized + ?Forget + 'static, + U: ?Sized + ?Forget + 'static, +{ + #[inline] + fn partial_cmp(&self, other: &ForgetStatic) -> Option { + self.0.partial_cmp(&other.0) + } +} diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index c7d596d74c383..bf8508fd993b2 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -1,3 +1,4 @@ +use crate::marker::Forget; use crate::pin::Pin; /// The result of a coroutine resumption. @@ -8,7 +9,7 @@ use crate::pin::Pin; #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[lang = "coroutine_state"] #[unstable(feature = "coroutine_trait", issue = "43122")] -pub enum CoroutineState { +pub enum CoroutineState { /// The coroutine suspended with a value. /// /// This state indicates that a coroutine has been suspended, and typically @@ -70,7 +71,7 @@ pub enum CoroutineState { #[unstable(feature = "coroutine_trait", issue = "43122")] #[fundamental] #[must_use = "coroutines are lazy and do nothing unless resumed"] -pub trait Coroutine { +pub trait Coroutine: ?Forget { /// The type of value this coroutine yields. /// /// This associated type corresponds to the `yield` expression and the @@ -78,7 +79,7 @@ pub trait Coroutine { /// For example an iterator-as-a-coroutine would likely have this type as /// `T`, the type being iterated over. #[lang = "coroutine_yield"] - type Yield; + type Yield: ?Forget; /// The type of value this coroutine returns. /// @@ -87,7 +88,7 @@ pub trait Coroutine { /// literal. For example futures would use this as `Result` as it /// represents a completed future. #[lang = "coroutine_return"] - type Return; + type Return: ?Forget; /// Resumes the execution of this coroutine. /// diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index b20e818cf9fc6..747320f349706 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -136,12 +136,12 @@ use crate::marker::{Forget, PointeeSized}; #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -pub const trait Deref: PointeeSized { +pub const trait Deref: PointeeSized + ?Forget { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "deref_target"] #[lang = "deref_target"] - type Target: ?Sized; + type Target: ?Sized + ?Forget; /// Dereferences the value. #[must_use] @@ -152,7 +152,7 @@ pub const trait Deref: PointeeSized { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const Deref for &T { +impl const Deref for &T { type Target = T; #[rustc_diagnostic_item = "noop_method_deref"] @@ -162,11 +162,11 @@ impl const Deref for &T { } #[stable(feature = "rust1", since = "1.0.0")] -impl !DerefMut for &T {} +impl !DerefMut for &T {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const Deref for &mut T { +impl const Deref for &mut T { type Target = T; fn deref(&self) -> &T { @@ -267,7 +267,7 @@ impl const Deref for &mut T { #[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -pub const trait DerefMut: [const] Deref + PointeeSized { +pub const trait DerefMut: [const] Deref + PointeeSized + ?Forget { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "deref_mut_method"] @@ -276,7 +276,7 @@ pub const trait DerefMut: [const] Deref + PointeeSized { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const DerefMut for &mut T { +impl const DerefMut for &mut T { fn deref_mut(&mut self) -> &mut T { self } @@ -293,13 +293,13 @@ impl const DerefMut for &mut T { /// unchanged. #[unstable(feature = "deref_pure_trait", issue = "87121")] #[lang = "deref_pure"] -pub unsafe trait DerefPure: PointeeSized {} +pub unsafe trait DerefPure: PointeeSized + ?Forget {} #[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl DerefPure for &T {} +unsafe impl DerefPure for &T {} #[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl DerefPure for &mut T {} +unsafe impl DerefPure for &mut T {} /// Indicates that a struct can be used as a method receiver. /// That is, a type can use this type as a type of `self`, like this: diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 479368ba8f801..5d543f6c5f2ac 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -1,4 +1,4 @@ -use crate::marker::Tuple; +use crate::marker::{Forget, Tuple}; /// The version of the call operator that takes an immutable receiver. /// @@ -73,7 +73,7 @@ use crate::marker::Tuple; #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] -pub const trait Fn: FnMut { +pub const trait Fn: FnMut + ?Forget { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call(&self, args: Args) -> Self::Output; @@ -160,7 +160,7 @@ pub const trait Fn: FnMut { #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] -pub const trait FnMut: FnOnce { +pub const trait FnMut: FnOnce + ?Forget { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; @@ -239,11 +239,11 @@ pub const trait FnMut: FnOnce { #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] -pub const trait FnOnce { +pub const trait FnOnce: ?Forget { /// The returned type after the call operator is used. #[lang = "fn_once_output"] #[stable(feature = "fn_once_output", since = "1.12.0")] - type Output; + type Output: ?Forget; /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -251,11 +251,11 @@ pub const trait FnOnce { } mod impls { - use crate::marker::Tuple; + use crate::marker::{Forget, Tuple}; #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] - impl const Fn for &F + impl const Fn for &F where F: [const] Fn, { @@ -266,7 +266,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] - impl const FnMut for &F + impl const FnMut for &F where F: [const] Fn, { @@ -277,7 +277,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] - impl const FnOnce for &F + impl const FnOnce for &F where F: [const] Fn, { @@ -290,7 +290,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] - impl const FnMut for &mut F + impl const FnMut for &mut F where F: [const] FnMut, { @@ -301,7 +301,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] - impl const FnOnce for &mut F + impl const FnOnce for &mut F where F: [const] FnMut, { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 430ee3470ac3f..03eeec80f533f 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -577,7 +577,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FusedIterator, TrustedLen}; -use crate::marker::Destruct; +use crate::marker::{Destruct, Forget}; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::panicking::{panic, panic_display}; use crate::pin::Pin; @@ -591,7 +591,7 @@ use crate::{cmp, convert, hint, mem, slice}; #[lang = "Option"] #[stable(feature = "rust1", since = "1.0.0")] #[allow(clippy::derived_hash_with_manual_eq)] // PartialEq is manually implemented equivalently -pub enum Option { +pub enum Option { /// No value. #[lang = "None"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2184,7 +2184,7 @@ const fn expect_failed(msg: &str) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] -impl const Clone for Option +impl const Clone for Option where // FIXME(const_hack): the T: [const] Destruct should be inferred from the Self: [const] Destruct in clone_from. // See https://github.com/rust-lang/rust/issues/144207 diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 10dbdfa1f4398..ba419e7b99db5 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -921,6 +921,7 @@ #![stable(feature = "pin", since = "1.33.0")] use crate::hash::{Hash, Hasher}; +use crate::marker::Forget; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; #[allow(unused_imports)] use crate::{ @@ -1516,7 +1517,7 @@ impl Pin { } } -impl<'a, T: ?Sized> Pin<&'a T> { +impl<'a, T: ?Sized + ?Forget> Pin<&'a T> { /// Constructs a new pin by mapping the interior value. /// /// For example, if you wanted to get a `Pin` of a field of something, @@ -1690,6 +1691,8 @@ impl const Deref for Pin { } mod helper { + use crate::marker::Forget; + /// Helper that prevents downstream crates from implementing `DerefMut` for `Pin`. /// /// The `Pin` type implements the unsafe trait `PinCoerceUnsized`, which essentially requires @@ -1719,7 +1722,7 @@ mod helper { #[rustc_const_unstable(feature = "const_convert", issue = "143773")] #[rustc_diagnostic_item = "PinDerefMutHelper"] pub const trait PinDerefMutHelper { - type Target: ?Sized; + type Target: ?Sized + ?Forget; fn deref_mut(&mut self) -> &mut Self::Target; } From fc3e66f0e628ef49bc969301b88e089c7700bc57 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Tue, 23 Dec 2025 21:38:37 +0300 Subject: [PATCH 6/6] Add Box support --- library/alloc/src/boxed.rs | 6 +- library/core/src/alloc/layout.rs | 7 +- library/core/src/array/mod.rs | 4 +- library/core/src/cmp.rs | 6 +- library/core/src/convert/mod.rs | 6 +- library/core/src/fmt/mod.rs | 2 +- library/core/src/intrinsics/bounds.rs | 26 +- library/core/src/intrinsics/mod.rs | 54 ++-- library/core/src/marker.rs | 16 +- library/core/src/mem/manually_drop.rs | 27 +- library/core/src/mem/maybe_uninit.rs | 351 ++++++++++---------- library/core/src/mem/mod.rs | 14 +- library/core/src/mem/transmutability.rs | 10 +- library/core/src/ops/control_flow.rs | 93 +++--- library/core/src/ops/drop.rs | 4 +- library/core/src/ops/unsize.rs | 4 +- library/core/src/option.rs | 4 +- library/core/src/pin.rs | 12 +- library/core/src/ptr/alignment.rs | 3 +- library/core/src/ptr/const_ptr.rs | 300 ++++++++--------- library/core/src/ptr/metadata.rs | 30 +- library/core/src/ptr/mod.rs | 40 +-- library/core/src/ptr/mut_ptr.rs | 408 ++++++++++++------------ library/core/src/ptr/non_null.rs | 40 ++- library/core/src/ptr/unique.rs | 14 +- library/core/src/result.rs | 6 +- library/core/src/slice/mod.rs | 5 +- 27 files changed, 762 insertions(+), 730 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 49ff768bed1b2..d798bda31e68e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -191,7 +191,7 @@ use core::error::{self, Error}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -use core::marker::{Tuple, Unsize}; +use core::marker::{Forget, Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, @@ -229,7 +229,7 @@ pub use thin::ThinBox; // The declaration of the `Box` struct must be kept in sync with the // compiler or ICEs will happen. pub struct Box< - T: ?Sized, + T: ?Sized + ?Forget, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, >(Unique, A); @@ -1672,7 +1672,7 @@ impl Box { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { +unsafe impl<#[may_dangle] T: ?Sized + ?Forget, A: Allocator> Drop for Box { #[inline] fn drop(&mut self) { // the T in the Box is dropped by the compiler before the destructor is run diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index cd5fd77f86597..71a20d8bc7204 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -6,6 +6,7 @@ use crate::error::Error; use crate::intrinsics::{unchecked_add, unchecked_mul, unchecked_sub}; +use crate::marker::Forget; use crate::mem::SizedTypeProperties; use crate::ptr::{Alignment, NonNull}; use crate::{assert_unsafe_precondition, fmt, mem}; @@ -16,7 +17,7 @@ use crate::{assert_unsafe_precondition, fmt, mem}; // // * https://github.com/rust-lang/rust/pull/72189 // * https://github.com/rust-lang/rust/pull/79827 -const fn size_align() -> (usize, usize) { +const fn size_align() -> (usize, usize) { (size_of::(), align_of::()) } @@ -167,7 +168,7 @@ impl Layout { #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")] #[must_use] #[inline] - pub const fn new() -> Self { + pub const fn new() -> Self { let (size, align) = size_align::(); // SAFETY: if the type is instantiated, rustc already ensures that its // layout is valid. Use the unchecked constructor to avoid inserting a @@ -217,7 +218,7 @@ impl Layout { /// [extern type]: ../../unstable-book/language-features/extern-types.html #[unstable(feature = "layout_for_ptr", issue = "69835")] #[must_use] - pub const unsafe fn for_value_raw(t: *const T) -> Self { + pub const unsafe fn for_value_raw(t: *const T) -> Self { // SAFETY: we pass along the prerequisites of these functions to the caller let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) }; // SAFETY: see rationale in `new` for why this is using the unsafe variant diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 0dc10758a8560..b2c03c005335a 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -12,6 +12,7 @@ use crate::fmt; use crate::hash::{self, Hash}; use crate::intrinsics::transmute_unchecked; use crate::iter::{UncheckedIterator, repeat_n}; +use crate::marker::Forget; use crate::mem::{self, MaybeUninit}; use crate::ops::{ ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try, @@ -146,6 +147,7 @@ pub fn try_from_fn(cb: F) -> ChangeOutputType R, R: Try, + R::Output: Forget, R::Residual: Residual<[R::Output; N]>, { let mut array = [const { MaybeUninit::uninit() }; N]; @@ -582,7 +584,7 @@ impl [T; N] { #[unstable(feature = "array_try_map", issue = "79711")] pub fn try_map(self, f: impl FnMut(T) -> R) -> ChangeOutputType where - R: Try>, + R: Try>, { drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f))) } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index ec491b13e740b..b3455cc384b09 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -337,7 +337,7 @@ pub macro PartialEq($item:item) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Eq"] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -pub const trait Eq: [const] PartialEq + PointeeSized { +pub const trait Eq: [const] PartialEq + PointeeSized + ?Forget { // this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a // type implements `Eq` itself. The current deriving infrastructure means doing this assertion // without using a method on this trait is nearly impossible. @@ -366,7 +366,7 @@ pub macro Eq($item:item) { #[doc(hidden)] #[allow(missing_debug_implementations)] #[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")] -pub struct AssertParamIsEq { +pub struct AssertParamIsEq { _field: crate::marker::PhantomData, } @@ -968,7 +968,7 @@ impl Clone for Reverse { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Ord"] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -pub const trait Ord: [const] Eq + [const] PartialOrd + PointeeSized { +pub const trait Ord: [const] Eq + [const] PartialOrd + PointeeSized + ?Forget { /// This method returns an [`Ordering`] between `self` and `other`. /// /// By convention, `self.cmp(&other)` returns the ordering matching the expression diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index e9bda3eae68bc..6138d173203d0 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -448,7 +448,7 @@ pub const trait AsMut: PointeeSized + ?Forget { #[stable(feature = "rust1", since = "1.0.0")] #[doc(search_unbox)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -pub const trait Into: Sized { +pub const trait Into: Sized + ?Forget { /// Converts this type into the (usually inferred) input type. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -764,7 +764,7 @@ where // From implies Into #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const Into for T +impl const Into for T where U: [const] From, { @@ -782,7 +782,7 @@ where // From (and thus Into) is reflexive #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From for T { +impl const From for T { /// Returns the argument unchanged. #[inline(always)] fn from(t: T) -> T { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e419de4250b38..33e09b69fd862 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1308,7 +1308,7 @@ pub trait UpperHex: PointeeSized { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Pointer"] -pub trait Pointer: PointeeSized { +pub trait Pointer: PointeeSized + ?Forget { #[doc = include_str!("fmt_trait_method_doc.md")] #[stable(feature = "rust1", since = "1.0.0")] fn fmt(&self, f: &mut Formatter<'_>) -> Result; diff --git a/library/core/src/intrinsics/bounds.rs b/library/core/src/intrinsics/bounds.rs index 353908598d40b..e0770889c9f60 100644 --- a/library/core/src/intrinsics/bounds.rs +++ b/library/core/src/intrinsics/bounds.rs @@ -1,41 +1,41 @@ //! Various traits used to restrict intrinsics to not-completely-wrong types. -use crate::marker::PointeeSized; +use crate::marker::{Forget, PointeeSized}; /// Types with a built-in dereference operator in runtime MIR, /// aka references and raw pointers. /// /// # Safety /// Must actually *be* such a type. -pub unsafe trait BuiltinDeref: Sized { - type Pointee: PointeeSized; +pub unsafe trait BuiltinDeref: Sized + ?Forget { + type Pointee: PointeeSized + ?Forget; } -unsafe impl BuiltinDeref for &mut T { +unsafe impl BuiltinDeref for &mut T { type Pointee = T; } -unsafe impl BuiltinDeref for &T { +unsafe impl BuiltinDeref for &T { type Pointee = T; } -unsafe impl BuiltinDeref for *mut T { +unsafe impl BuiltinDeref for *mut T { type Pointee = T; } -unsafe impl BuiltinDeref for *const T { +unsafe impl BuiltinDeref for *const T { type Pointee = T; } -pub trait ChangePointee: BuiltinDeref { - type Output; +pub trait ChangePointee: BuiltinDeref + ?Forget { + type Output: ?Forget; } -impl<'a, T: PointeeSized + 'a, U: PointeeSized + 'a> ChangePointee for &'a mut T { +impl<'a, T: PointeeSized + ?Forget + 'a, U: PointeeSized + ?Forget + 'a> ChangePointee for &'a mut T { type Output = &'a mut U; } -impl<'a, T: PointeeSized + 'a, U: PointeeSized + 'a> ChangePointee for &'a T { +impl<'a, T: PointeeSized + ?Forget + 'a, U: PointeeSized + ?Forget + 'a> ChangePointee for &'a T { type Output = &'a U; } -impl ChangePointee for *mut T { +impl ChangePointee for *mut T { type Output = *mut U; } -impl ChangePointee for *const T { +impl ChangePointee for *const T { type Output = *const U; } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 636a02a35aef4..e80cf2283697b 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -835,7 +835,7 @@ pub const unsafe fn forget(_: T); #[rustc_diagnostic_item = "transmute"] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn transmute(src: Src) -> Dst; +pub const unsafe fn transmute(src: Src) -> Dst; /// Like [`transmute`], but even less checked at compile-time: rather than /// giving an error for `size_of::() != size_of::()`, it's @@ -849,7 +849,7 @@ pub const unsafe fn transmute(src: Src) -> Dst; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn transmute_unchecked(src: Src) -> Dst; +pub const unsafe fn transmute_unchecked(src: Src) -> Dst; /// Returns `true` if the actual type given as `T` requires drop /// glue; returns `false` if the actual type provided for `T` @@ -889,7 +889,7 @@ pub const fn needs_drop() -> bool; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn offset(dst: Ptr, offset: Delta) -> Ptr; +pub const unsafe fn offset(dst: Ptr, offset: Delta) -> Ptr; /// Calculates the offset from a pointer, potentially wrapping. /// @@ -908,7 +908,7 @@ pub const unsafe fn offset(dst: Ptr, offset: D #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn arith_offset(dst: *const T, offset: isize) -> *const T; +pub const unsafe fn arith_offset(dst: *const T, offset: isize) -> *const T; /// Projects to the `index`-th element of `slice_ptr`, as the same kind of pointer /// as the slice was provided -- so `&mut [T] → &mut T`, `&[T] → &T`, @@ -946,7 +946,7 @@ pub const unsafe fn slice_get_unchecked< /// Consider using [`pointer::mask`] instead. #[rustc_nounwind] #[rustc_intrinsic] -pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T; +pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::()` and an alignment of `align_of::()`. @@ -961,7 +961,7 @@ pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T; /// [`copy_nonoverlapping`]: ptr::copy_nonoverlapping #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: usize); +pub unsafe fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with /// a size of `count * size_of::()` and an alignment of `align_of::()`. /// @@ -971,7 +971,7 @@ pub unsafe fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); +pub unsafe fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a /// size of `count * size_of::()` and an alignment of `align_of::()`. /// @@ -984,20 +984,20 @@ pub unsafe fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); /// [`write_bytes`]: ptr::write_bytes #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_set_memory(dst: *mut T, val: u8, count: usize); +pub unsafe fn volatile_set_memory(dst: *mut T, val: u8, count: usize); /// Performs a volatile load from the `src` pointer. /// /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_load(src: *const T) -> T; +pub unsafe fn volatile_load(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_store(dst: *mut T, val: T); +pub unsafe fn volatile_store(dst: *mut T, val: T); /// Performs a volatile load from the `src` pointer /// The pointer is not required to be aligned. @@ -1006,7 +1006,7 @@ pub unsafe fn volatile_store(dst: *mut T, val: T); #[rustc_intrinsic] #[rustc_nounwind] #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] -pub unsafe fn unaligned_volatile_load(src: *const T) -> T; +pub unsafe fn unaligned_volatile_load(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// The pointer is not required to be aligned. /// @@ -1014,7 +1014,7 @@ pub unsafe fn unaligned_volatile_load(src: *const T) -> T; #[rustc_intrinsic] #[rustc_nounwind] #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] -pub unsafe fn unaligned_volatile_store(dst: *mut T, val: T); +pub unsafe fn unaligned_volatile_store(dst: *mut T, val: T); /// Returns the square root of an `f16` /// @@ -2166,7 +2166,7 @@ pub const unsafe fn unchecked_funnel_shr( #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn read_via_copy(ptr: *const T) -> T; +pub const unsafe fn read_via_copy(ptr: *const T) -> T; /// This is an implementation detail of [`crate::ptr::write`] and should /// not be used anywhere else. See its comments for why this exists. @@ -2177,7 +2177,7 @@ pub const unsafe fn read_via_copy(ptr: *const T) -> T; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn write_via_move(ptr: *mut T, value: T); +pub const unsafe fn write_via_move(ptr: *mut T, value: T); /// Returns the value of the discriminant for the variant in 'v'; /// if `T` has no discriminant, returns `0`. @@ -2226,19 +2226,19 @@ pub unsafe fn catch_unwind( /// in ways that are not allowed for regular writes). #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn nontemporal_store(ptr: *mut T, val: T); +pub unsafe fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; +pub const unsafe fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// See documentation of `<*const T>::offset_from_unsigned` for details. #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_const_stable_indirect] -pub const unsafe fn ptr_offset_from_unsigned(ptr: *const T, base: *const T) -> usize; +pub const unsafe fn ptr_offset_from_unsigned(ptr: *const T, base: *const T) -> usize; /// See documentation of `<*const T>::guaranteed_eq` for details. /// Returns `2` if the result is unknown. @@ -2249,7 +2249,7 @@ pub const unsafe fn ptr_offset_from_unsigned(ptr: *const T, base: *const T) - #[rustc_do_not_const_check] #[inline] #[miri::intrinsic_fallback_is_spec] -pub const fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8 { +pub const fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8 { (ptr == other) as u8 } @@ -2740,7 +2740,7 @@ pub unsafe fn vtable_align(ptr: *const ()) -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn size_of() -> usize; +pub const fn size_of() -> usize; /// The minimum alignment of a type. /// @@ -2754,7 +2754,7 @@ pub const fn size_of() -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn align_of() -> usize; +pub const fn align_of() -> usize; /// Returns the number of variants of the type `T` cast to a `usize`; /// if `T` has no variants, returns `0`. Uninhabited variants will be counted. @@ -2768,7 +2768,7 @@ pub const fn align_of() -> usize; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -pub const fn variant_count() -> usize; +pub const fn variant_count() -> usize; /// The size of the referenced value in bytes. /// @@ -2781,7 +2781,7 @@ pub const fn variant_count() -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_const_stable_indirect] -pub const unsafe fn size_of_val(ptr: *const T) -> usize; +pub const unsafe fn size_of_val(ptr: *const T) -> usize; /// The required alignment of the referenced value. /// @@ -2794,7 +2794,7 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_const_stable_indirect] -pub const unsafe fn align_of_val(ptr: *const T) -> usize; +pub const unsafe fn align_of_val(ptr: *const T) -> usize; /// Gets a static string slice containing the name of a type. /// @@ -2846,7 +2846,7 @@ pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn aggregate_raw_ptr(data: D, meta: M) -> P +pub const fn aggregate_raw_ptr(data: D, meta: M) -> P where

::Pointee: ptr::Pointee; @@ -2870,7 +2870,7 @@ pub const fn ptr_metadata + PointeeSized + ?Forget #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); +pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); /// This is an accidentally-stable alias to [`ptr::copy`]; use that instead. // Note (intentionally not in the doc comment): `ptr::copy` adds some extra @@ -2881,7 +2881,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize); +pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize); /// This is an accidentally-stable alias to [`ptr::write_bytes`]; use that instead. // Note (intentionally not in the doc comment): `ptr::write_bytes` adds some extra @@ -2892,7 +2892,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize); #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize); +pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize); /// Returns the minimum (IEEE 754-2008 minNum) of two `f16` values. /// diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d39df4ec45be7..60f2bafb703c3 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -158,7 +158,7 @@ unsafe impl Send for &T {} // and we know that the supertraits are always implemented if the subtrait is just by looking at // the builtin impls. #[rustc_coinductive] -pub trait Sized: MetaSized { +pub trait Sized: MetaSized + ?Forget { // Empty. } @@ -237,7 +237,7 @@ pub trait PointeeSized: ?Forget { #[lang = "unsize"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Unsize: PointeeSized { +pub trait Unsize: PointeeSized + ?Forget { // Empty. } @@ -518,7 +518,7 @@ impl Copy for &T {} #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] #[doc(hidden)] -pub trait BikeshedGuaranteedNoDrop {} +pub trait BikeshedGuaranteedNoDrop: ?Forget {} /// Types for which it is safe to share references between threads. /// @@ -820,7 +820,7 @@ impl !Sync for *mut T {} /// [drop check]: Drop#drop-check #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct PhantomData; +pub struct PhantomData; #[stable(feature = "rust1", since = "1.0.0")] impl Hash for PhantomData { @@ -914,7 +914,7 @@ pub trait DiscriminantKind: ?Forget { pub unsafe auto trait Freeze {} #[unstable(feature = "freeze", issue = "121675")] -impl !Freeze for UnsafeCell {} +impl !Freeze for UnsafeCell {} marker_impls! { #[unstable(feature = "freeze", issue = "121675")] unsafe Freeze for @@ -934,7 +934,7 @@ marker_impls! { #[lang = "unsafe_unpin"] pub(crate) unsafe auto trait UnsafeUnpin {} -impl !UnsafeUnpin for UnsafePinned {} +impl !UnsafeUnpin for UnsafePinned {} unsafe impl UnsafeUnpin for PhantomData {} unsafe impl UnsafeUnpin for *const T {} unsafe impl UnsafeUnpin for *mut T {} @@ -1058,7 +1058,7 @@ marker_impls! { #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub const trait Destruct {} +pub const trait Destruct: ?Forget {} /// A marker for tuple types. /// @@ -1354,8 +1354,6 @@ pub unsafe auto trait Forget { marker_impls! { #[unstable(feature = "forget_trait", issue = "none")] unsafe Forget for - {T: ?Sized + ?Forget} *const T, - {T: ?Sized + ?Forget} *mut T, {T: ?Sized + ?Forget} &T, {T: ?Sized + ?Forget} &mut T, } diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 9043318677b7e..781c17785e774 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -185,6 +185,20 @@ impl ManuallyDrop { ManuallyDrop { value } } +} + +impl ManuallyDrop { + /// Unchecked version of [`ManuallyDrop::new`] where `T` might not implement [`Forget`]. + /// + /// # Safety + /// + /// Caller must ensure `value` is dropped according to type's safety invariants. + #[unstable(feature = "forget_trait", issue = "none")] + #[inline(always)] + pub const unsafe fn new_unchecked(value: T) -> ManuallyDrop { + ManuallyDrop { value } + } + /// Extracts the value from the `ManuallyDrop` container. /// /// This allows the value to be dropped again. @@ -228,19 +242,6 @@ impl ManuallyDrop { } } -impl ManuallyDrop { - /// Unchecked version of [`ManuallyDrop::new`] where `T` might not implement [`Forget`]. - /// - /// # Safety - /// - /// Caller must ensure `value` is dropped according to type's safety invariants. - #[unstable(feature = "forget_trait", issue = "none")] - #[inline(always)] - pub const unsafe fn new_unchecked(value: T) -> ManuallyDrop { - ManuallyDrop { value } - } -} - impl ManuallyDrop { /// Manually drops the contained value. /// diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f6cd9887ffb65..1d6c0431ba9b8 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -312,81 +312,6 @@ impl MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } } - /// Creates a new `MaybeUninit` in an uninitialized state. - /// - /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// See the [type-level documentation][MaybeUninit] for some examples. - /// - /// # Example - /// - /// ``` - /// use std::mem::MaybeUninit; - /// - /// let v: MaybeUninit = MaybeUninit::uninit(); - /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] - #[must_use] - #[inline(always)] - #[rustc_diagnostic_item = "maybe_uninit_uninit"] - pub const fn uninit() -> MaybeUninit { - MaybeUninit { uninit: () } - } - - /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being - /// filled with `0` bytes. It depends on `T` whether that already makes for - /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, - /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not - /// be null. - /// - /// Note that if `T` has padding bytes, those bytes are *not* preserved when the - /// `MaybeUninit` value is returned from this function, so those bytes will *not* be zeroed. - /// - /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// # Example - /// - /// Correct usage of this function: initializing a struct with zero, where all - /// fields of the struct can hold the bit-pattern 0 as a valid value. - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::<(u8, bool)>::zeroed(); - /// let x = unsafe { x.assume_init() }; - /// assert_eq!(x, (0, false)); - /// ``` - /// - /// This can be used in const contexts, such as to indicate the end of static arrays for - /// plugin registration. - /// - /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` - /// when `0` is not a valid bit-pattern for the type: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// enum NotZero { One = 1, Two = 2 } - /// - /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); - /// let x = unsafe { x.assume_init() }; - /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. - /// // This is undefined behavior. ⚠️ - /// ``` - #[inline] - #[must_use] - #[rustc_diagnostic_item = "maybe_uninit_zeroed"] - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "1.75.0")] - pub const fn zeroed() -> MaybeUninit { - let mut u = MaybeUninit::::uninit(); - // SAFETY: `u.as_mut_ptr()` points to allocated memory. - unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; - u - } /// Sets the value of the `MaybeUninit`. /// @@ -482,66 +407,6 @@ impl MaybeUninit { unsafe { self.write_unchecked(val) } } - /// Extracts the value from the `MaybeUninit` container. This is a great way - /// to ensure that the data will get dropped, because the resulting `T` is - /// subject to the usual drop handling. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes immediate undefined - /// behavior. The [type-level documentation][inv] contains more information about - /// this initialization invariant. - /// - /// [inv]: #initialization-invariant - /// - /// On top of that, remember that most types have additional invariants beyond merely - /// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] - /// is considered initialized (under the current implementation; this does not constitute - /// a stable guarantee) because the only requirement the compiler knows about it - /// is that the data pointer must be non-null. Creating such a `Vec` does not cause - /// *immediate* undefined behavior, but will cause undefined behavior with most - /// safe operations (including dropping it). - /// - /// [`Vec`]: ../../std/vec/struct.Vec.html - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::::uninit(); - /// x.write(true); - /// let x_init = unsafe { x.assume_init() }; - /// assert_eq!(x_init, true); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::>::uninit(); - /// let x_init = unsafe { x.assume_init() }; - /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ - /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_by_value", since = "1.59.0")] - #[inline(always)] - #[rustc_diagnostic_item = "assume_init"] - #[track_caller] - pub const unsafe fn assume_init(self) -> T { - // SAFETY: the caller must guarantee that `self` is initialized. - // This also means that `self` must be a `value` variant. - unsafe { - intrinsics::assert_inhabited::(); - // We do this via a raw ptr read instead of `ManuallyDrop::into_inner` so that there's - // no trace of `ManuallyDrop` in Miri's error messages here. - (&raw const self.value).cast::().read() - } - } /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject /// to the usual drop handling. @@ -713,45 +578,6 @@ impl MaybeUninit { } } - /// Extracts the values from an array of `MaybeUninit` containers. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that all elements of the array are - /// in an initialized state. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_array_assume_init)] - /// use std::mem::MaybeUninit; - /// - /// let mut array: [MaybeUninit; 3] = [MaybeUninit::uninit(); 3]; - /// array[0].write(0); - /// array[1].write(1); - /// array[2].write(2); - /// - /// // SAFETY: Now safe as we initialised all elements - /// let array = unsafe { - /// MaybeUninit::array_assume_init(array) - /// }; - /// - /// assert_eq!(array, [0, 1, 2]); - /// ``` - #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")] - #[inline(always)] - #[track_caller] - pub const unsafe fn array_assume_init(array: [Self; N]) -> [T; N] { - // SAFETY: - // * The caller guarantees that all elements of the array are initialized - // * `MaybeUninit` and T are guaranteed to have the same layout - // * `MaybeUninit` does not drop, so there are no double-frees - // And thus the conversion is safe - unsafe { - intrinsics::assert_inhabited::<[T; N]>(); - intrinsics::transmute_unchecked(array) - } - } /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// @@ -839,6 +665,143 @@ impl MaybeUninit { MaybeUninit { value: unsafe { ManuallyDrop::new_unchecked(val) } } } + /// Creates a new `MaybeUninit` in an uninitialized state. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// See the [type-level documentation][MaybeUninit] for some examples. + /// + /// # Example + /// + /// ``` + /// use std::mem::MaybeUninit; + /// + /// let v: MaybeUninit = MaybeUninit::uninit(); + /// ``` + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] + #[must_use] + #[inline(always)] + #[rustc_diagnostic_item = "maybe_uninit_uninit"] + pub const fn uninit() -> MaybeUninit { + MaybeUninit { uninit: () } + } + + /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being + /// filled with `0` bytes. It depends on `T` whether that already makes for + /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, + /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not + /// be null. + /// + /// Note that if `T` has padding bytes, those bytes are *not* preserved when the + /// `MaybeUninit` value is returned from this function, so those bytes will *not* be zeroed. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// # Example + /// + /// Correct usage of this function: initializing a struct with zero, where all + /// fields of the struct can hold the bit-pattern 0 as a valid value. + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::<(u8, bool)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// assert_eq!(x, (0, false)); + /// ``` + /// + /// This can be used in const contexts, such as to indicate the end of static arrays for + /// plugin registration. + /// + /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` + /// when `0` is not a valid bit-pattern for the type: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// enum NotZero { One = 1, Two = 2 } + /// + /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. + /// // This is undefined behavior. ⚠️ + /// ``` + #[inline] + #[must_use] + #[rustc_diagnostic_item = "maybe_uninit_zeroed"] + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "1.75.0")] + pub const fn zeroed() -> MaybeUninit { + let mut u = MaybeUninit::::uninit(); + // SAFETY: `u.as_mut_ptr()` points to allocated memory. + unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; + u + } + + /// Extracts the value from the `MaybeUninit` container. This is a great way + /// to ensure that the data will get dropped, because the resulting `T` is + /// subject to the usual drop handling. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes immediate undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// [inv]: #initialization-invariant + /// + /// On top of that, remember that most types have additional invariants beyond merely + /// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] + /// is considered initialized (under the current implementation; this does not constitute + /// a stable guarantee) because the only requirement the compiler knows about it + /// is that the data pointer must be non-null. Creating such a `Vec` does not cause + /// *immediate* undefined behavior, but will cause undefined behavior with most + /// safe operations (including dropping it). + /// + /// [`Vec`]: ../../std/vec/struct.Vec.html + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// x.write(true); + /// let x_init = unsafe { x.assume_init() }; + /// assert_eq!(x_init, true); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_init = unsafe { x.assume_init() }; + /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ + /// ``` + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_by_value", since = "1.59.0")] + #[inline(always)] + #[rustc_diagnostic_item = "assume_init"] + #[track_caller] + pub const unsafe fn assume_init(self) -> T { + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::(); + // We do this via a raw ptr read instead of `ManuallyDrop::into_inner` so that there's + // no trace of `ManuallyDrop` in Miri's error messages here. + (&raw const self.value).cast::().read() + } + } + /// Gets a mutable (unique) reference to the contained value. /// /// This can be useful when we want to access a `MaybeUninit` that has been @@ -1054,6 +1017,46 @@ impl MaybeUninit { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. self as *mut _ as *mut T } + + /// Extracts the values from an array of `MaybeUninit` containers. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that all elements of the array are + /// in an initialized state. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_array_assume_init)] + /// use std::mem::MaybeUninit; + /// + /// let mut array: [MaybeUninit; 3] = [MaybeUninit::uninit(); 3]; + /// array[0].write(0); + /// array[1].write(1); + /// array[2].write(2); + /// + /// // SAFETY: Now safe as we initialised all elements + /// let array = unsafe { + /// MaybeUninit::array_assume_init(array) + /// }; + /// + /// assert_eq!(array, [0, 1, 2]); + /// ``` + #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")] + #[inline(always)] + #[track_caller] + pub const unsafe fn array_assume_init(array: [Self; N]) -> [T; N] { + // SAFETY: + // * The caller guarantees that all elements of the array are initialized + // * `MaybeUninit` and T are guaranteed to have the same layout + // * `MaybeUninit` does not drop, so there are no double-frees + // And thus the conversion is safe + unsafe { + intrinsics::assert_inhabited::<[T; N]>(); + intrinsics::transmute_unchecked(array) + } + } } impl [MaybeUninit] { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 6d9439e91a31f..d1c5cee543d0e 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -354,7 +354,7 @@ pub unsafe fn forget_unsized_unchecked(t: T) { #[rustc_promotable] #[rustc_const_stable(feature = "const_mem_size_of", since = "1.24.0")] #[rustc_diagnostic_item = "mem_size_of"] -pub const fn size_of() -> usize { +pub const fn size_of() -> usize { intrinsics::size_of::() } @@ -437,7 +437,7 @@ pub const fn size_of_val(val: &T) -> usize { #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] -pub const unsafe fn size_of_val_raw(val: *const T) -> usize { +pub const unsafe fn size_of_val_raw(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer unsafe { intrinsics::size_of_val(val) } } @@ -509,7 +509,7 @@ pub fn min_align_of_val(val: &T) -> usize { #[rustc_promotable] #[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] #[rustc_diagnostic_item = "mem_align_of"] -pub const fn align_of() -> usize { +pub const fn align_of() -> usize { intrinsics::align_of::() } @@ -576,7 +576,7 @@ pub const fn align_of_val(val: &T) -> usize { #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] -pub const unsafe fn align_of_val_raw(val: *const T) -> usize { +pub const unsafe fn align_of_val_raw(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer unsafe { intrinsics::align_of_val(val) } } @@ -896,7 +896,7 @@ pub fn take(dest: &mut T) -> T { #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[rustc_diagnostic_item = "mem_replace"] -pub const fn replace(dest: &mut T, src: T) -> T { +pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! // The compiler optimizes the implementation below to two `memcpy`s // while `swap` would require at least three. See PR#83022 for details. @@ -1252,7 +1252,7 @@ pub const fn variant_count() -> usize { /// It's not on a stabilization track right now. #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] -pub trait SizedTypeProperties: Sized { +pub trait SizedTypeProperties: Sized + ?Forget { /// `true` if this type requires no storage. /// `false` if its [size](size_of) is greater than zero. /// @@ -1299,7 +1299,7 @@ pub trait SizedTypeProperties: Sized { } #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] -impl SizedTypeProperties for T {} +impl SizedTypeProperties for T {} /// Expands to the offset in bytes of a field from the beginning of the given type. /// diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index f36cb8cddb837..c61cd823c4975 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -1,4 +1,4 @@ -use crate::marker::ConstParamTy_; +use crate::marker::{ConstParamTy_, Forget}; /// Marks that `Src` is transmutable into `Self`. /// @@ -88,9 +88,9 @@ use crate::marker::ConstParamTy_; #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] #[rustc_coinductive] -pub unsafe trait TransmuteFrom +pub unsafe trait TransmuteFrom: ?Forget where - Src: ?Sized, + Src: ?Sized + ?Forget, { /// Transmutes a `Src` value into a `Self`. /// @@ -121,12 +121,12 @@ where use super::ManuallyDrop; #[repr(C)] - union Transmute { + union Transmute { src: ManuallyDrop, dst: ManuallyDrop, } - let transmute = Transmute { src: ManuallyDrop::new(src) }; + let transmute = Transmute { src: unsafe { ManuallyDrop::new_unchecked(src) } }; // SAFETY: It is safe to reinterpret the bits of `src` as a value of // type `Self`, because, by combination of invariant on this trait and diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index b760a7c4e21eb..91aee0eba185a 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -1,4 +1,4 @@ -use crate::{convert, ops}; +use crate::{convert, marker::Forget, ops}; /// Used to tell an operation whether it should exit early or go on as usual. /// @@ -85,7 +85,7 @@ use crate::{convert, ops}; // https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow #[derive(Copy, Debug, Hash)] #[derive_const(Clone, PartialEq, Eq)] -pub enum ControlFlow { +pub enum ControlFlow { /// Move on to the next phase of the operation as normal. #[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[lang = "Continue"] @@ -137,7 +137,7 @@ impl ops::Residual for ControlFlow { type TryType = ControlFlow; } -impl ControlFlow { +impl ControlFlow { /// Returns `true` if this is a `Break` variant. /// /// # Examples @@ -190,6 +190,52 @@ impl ControlFlow { } } + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the break value in case it exists. + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn map_break(self, f: impl FnOnce(B) -> T) -> ControlFlow { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(x), + ControlFlow::Break(x) => ControlFlow::Break(f(x)), + } + } + + /// Converts the `ControlFlow` into an `Option` which is `Some` if the + /// `ControlFlow` was `Continue` and `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert_eq!(ControlFlow::<&str, i32>::Break("Stop right there!").continue_value(), None); + /// assert_eq!(ControlFlow::<&str, i32>::Continue(3).continue_value(), Some(3)); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn continue_value(self) -> Option { + match self { + ControlFlow::Continue(x) => Some(x), + ControlFlow::Break(..) => None, + } + } + + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the continue value in case it exists. + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn map_continue(self, f: impl FnOnce(C) -> T) -> ControlFlow { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), + ControlFlow::Break(x) => ControlFlow::Break(x), + } + } +} + +impl ControlFlow { /// Converts the `ControlFlow` into an `Result` which is `Ok` if the /// `ControlFlow` was `Break` and `Err` if otherwise. /// @@ -264,37 +310,6 @@ impl ControlFlow { } } - /// Maps `ControlFlow` to `ControlFlow` by applying a function - /// to the break value in case it exists. - #[inline] - #[stable(feature = "control_flow_enum", since = "1.83.0")] - pub fn map_break(self, f: impl FnOnce(B) -> T) -> ControlFlow { - match self { - ControlFlow::Continue(x) => ControlFlow::Continue(x), - ControlFlow::Break(x) => ControlFlow::Break(f(x)), - } - } - - /// Converts the `ControlFlow` into an `Option` which is `Some` if the - /// `ControlFlow` was `Continue` and `None` otherwise. - /// - /// # Examples - /// - /// ``` - /// use std::ops::ControlFlow; - /// - /// assert_eq!(ControlFlow::<&str, i32>::Break("Stop right there!").continue_value(), None); - /// assert_eq!(ControlFlow::<&str, i32>::Continue(3).continue_value(), Some(3)); - /// ``` - #[inline] - #[stable(feature = "control_flow_enum", since = "1.83.0")] - pub fn continue_value(self) -> Option { - match self { - ControlFlow::Continue(x) => Some(x), - ControlFlow::Break(..) => None, - } - } - /// Converts the `ControlFlow` into an `Result` which is `Ok` if the /// `ControlFlow` was `Continue` and `Err` if otherwise. /// @@ -368,16 +383,6 @@ impl ControlFlow { } } - /// Maps `ControlFlow` to `ControlFlow` by applying a function - /// to the continue value in case it exists. - #[inline] - #[stable(feature = "control_flow_enum", since = "1.83.0")] - pub fn map_continue(self, f: impl FnOnce(C) -> T) -> ControlFlow { - match self { - ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), - ControlFlow::Break(x) => ControlFlow::Break(x), - } - } } impl ControlFlow { diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 7125bf54701bb..31d78192523a4 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -1,3 +1,5 @@ +use crate::marker::Forget; + /// Custom code within the destructor. /// /// When a value is no longer needed, Rust will run a "destructor" on that value. @@ -204,7 +206,7 @@ #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_destruct", issue = "133214")] -pub const trait Drop { +pub const trait Drop: ?Forget { /// Executes the destructor for this type. /// /// This method is called implicitly when the value goes out of scope, diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index bff8d2ccc5add..dd8d6d279043e 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -33,7 +33,7 @@ use crate::marker::{Forget, PointeeSized, Unsize}; /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "18598")] #[lang = "coerce_unsized"] -pub trait CoerceUnsized { +pub trait CoerceUnsized: ?Forget { // Empty. } @@ -131,7 +131,7 @@ impl, U: PointeeSized> CoerceUnsized<*cons /// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] -pub trait DispatchFromDyn { +pub trait DispatchFromDyn: ?Forget { // Empty. } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 03eeec80f533f..1367a28f84c90 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2343,10 +2343,10 @@ impl<'a, T> const From<&'a mut Option> for Option<&'a mut T> { // Once https://github.com/llvm/llvm-project/issues/52622 is fixed, we can // go back to deriving `PartialEq`. #[stable(feature = "rust1", since = "1.0.0")] -impl crate::marker::StructuralPartialEq for Option {} +impl crate::marker::StructuralPartialEq for Option {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -impl const PartialEq for Option { +impl const PartialEq for Option { #[inline] fn eq(&self, other: &Self) -> bool { // Spelling out the cases explicitly optimizes better than diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index ba419e7b99db5..50dacd1538da5 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1215,7 +1215,7 @@ impl> Pin { } } -impl Pin { +impl Pin { /// Constructs a new `Pin` around a reference to some data of a type that /// may or may not implement [`Unpin`]. /// @@ -1847,22 +1847,22 @@ where /// to. The concrete type of a slice is an array of the same element type and /// the length specified in the metadata. The concrete type of a sized type /// is the type itself. -pub unsafe trait PinCoerceUnsized {} +pub unsafe trait PinCoerceUnsized: ?Forget {} #[stable(feature = "pin", since = "1.33.0")] -unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {} +unsafe impl<'a, T: ?Sized + ?Forget> PinCoerceUnsized for &'a T {} #[stable(feature = "pin", since = "1.33.0")] -unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {} +unsafe impl<'a, T: ?Sized + ?Forget> PinCoerceUnsized for &'a mut T {} #[stable(feature = "pin", since = "1.33.0")] unsafe impl PinCoerceUnsized for Pin {} #[stable(feature = "pin", since = "1.33.0")] -unsafe impl PinCoerceUnsized for *const T {} +unsafe impl PinCoerceUnsized for *const T {} #[stable(feature = "pin", since = "1.33.0")] -unsafe impl PinCoerceUnsized for *mut T {} +unsafe impl PinCoerceUnsized for *mut T {} /// Constructs a [Pin]<[&mut] T>, by pinning a `value: T` locally. /// diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bc7d3a1de7151..2eb6856029b06 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,5 +1,6 @@ #![allow(clippy::enum_clike_unportable_variant)] +use crate::marker::Forget; use crate::num::NonZero; use crate::ub_checks::assert_unsafe_precondition; use crate::{cmp, fmt, hash, mem, num}; @@ -45,7 +46,7 @@ impl Alignment { #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] #[must_use] - pub const fn of() -> Self { + pub const fn of() -> Self { // This can't actually panic since type alignment is always a power of two. const { Alignment::new(align_of::()).unwrap() } } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 85939e812a90b..45ae30a0e029c 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -5,7 +5,7 @@ use crate::marker::Forget; use crate::mem::{self, SizedTypeProperties}; use crate::slice::{self, SliceIndex}; -impl *const T { +impl *const T { #[doc = include_str!("docs/is_null.md")] /// /// # Examples @@ -121,7 +121,7 @@ impl *const T { #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *const U where - U: PointeeSized, + U: PointeeSized + ?Forget, { from_raw_parts::(self as *const (), metadata(meta)) } @@ -138,6 +138,18 @@ impl *const T { self as _ } +} + +impl *const T { + /// Casts to a pointer of another type. + #[stable(feature = "ptr_cast", since = "1.38.0")] + #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] + #[rustc_diagnostic_item = "const_ptr_cast"] + #[inline(always)] + pub const fn cast(self) -> *const U { + self as _ + } + #[doc = include_str!("./docs/addr.md")] #[must_use] #[inline(always)] @@ -150,17 +162,6 @@ impl *const T { // provenance). unsafe { mem::transmute(self.cast::<()>()) } } -} - -impl *const T { - /// Casts to a pointer of another type. - #[stable(feature = "ptr_cast", since = "1.38.0")] - #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] - #[rustc_diagnostic_item = "const_ptr_cast"] - #[inline(always)] - pub const fn cast(self) -> *const U { - self as _ - } /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in /// [`with_exposed_provenance`] and returns the "address" portion. @@ -189,6 +190,118 @@ impl *const T { pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it. + /// See that method for documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] + #[inline] + #[track_caller] + pub const unsafe fn byte_offset_from_unsigned(self, origin: *const U) -> usize { + // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`. + unsafe { self.cast::().offset_from_unsigned(origin.cast::()) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of T: the distance in bytes is divided by `size_of::()`. + /// + /// This computes the same value that [`offset_from`](#method.offset_from) + /// would compute, but with the added precondition that the offset is + /// guaranteed to be non-negative. This method is equivalent to + /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, + /// but it provides slightly more information to the optimizer, which can + /// sometimes allow it to optimize slightly better with some backends. + /// + /// This method can be thought of as recovering the `count` that was passed + /// to [`add`](#method.add) (or, with the parameters in the other order, + /// to [`sub`](#method.sub)). The following are all equivalent, assuming + /// that their safety preconditions are met: + /// ```rust + /// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe { + /// ptr.offset_from_unsigned(origin) == count + /// # && + /// origin.add(count) == ptr + /// # && + /// ptr.sub(count) == origin + /// # } } + /// ``` + /// + /// # Safety + /// + /// - The distance between the pointers must be non-negative (`self >= origin`) + /// + /// - *All* the safety conditions of [`offset_from`](#method.offset_from) + /// apply to this method as well; see it for the full details. + /// + /// Importantly, despite the return type of this method being able to represent + /// a larger offset, it's still *not permitted* to pass pointers which differ + /// by more than `isize::MAX` *bytes*. As such, the result of this method will + /// always be less than or equal to `isize::MAX as usize`. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// ``` + /// let a = [0; 5]; + /// let ptr1: *const i32 = &a[1]; + /// let ptr2: *const i32 = &a[3]; + /// unsafe { + /// assert_eq!(ptr2.offset_from_unsigned(ptr1), 2); + /// assert_eq!(ptr1.add(2), ptr2); + /// assert_eq!(ptr2.sub(2), ptr1); + /// assert_eq!(ptr2.offset_from_unsigned(ptr2), 0); + /// } + /// + /// // This would be incorrect, as the pointers are not correctly ordered: + /// // ptr1.offset_from_unsigned(ptr2) + /// ``` + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] + #[inline] + #[track_caller] + pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize + where + T: Sized, + { + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool { + const_eval_select!( + @capture { this: *const (), origin: *const () } -> bool: + if const { + true + } else { + this >= origin + } + ) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::offset_from_unsigned requires `self >= origin`", + ( + this: *const () = self as *const (), + origin: *const () = origin as *const (), + ) => runtime_ptr_ge(this, origin) + ); + + let pointee_size = size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); + // SAFETY: the caller must uphold the safety contract for `ptr_offset_from_unsigned`. + unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } + } + } impl *const T { @@ -228,7 +341,9 @@ impl *const T { pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } +} +impl *const T { /// Decompose a (possibly wide) pointer into its data pointer and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. @@ -238,6 +353,27 @@ impl *const T { (self.cast(), metadata(self)) } + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// See [`ptr::read`] for safety concerns and examples. + /// + /// [`ptr::read`]: crate::ptr::read() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] + #[inline] + #[track_caller] + pub const unsafe fn read(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read`. + unsafe { read(self) } + } + +} + +impl *const T { #[doc = include_str!("./docs/as_ref.md")] /// /// ``` @@ -642,116 +778,6 @@ impl *const T { unsafe { self.cast::().offset_from(origin.cast::()) } } - /// Calculates the distance between two pointers within the same allocation, *where it's known that - /// `self` is equal to or greater than `origin`*. The returned value is in - /// units of T: the distance in bytes is divided by `size_of::()`. - /// - /// This computes the same value that [`offset_from`](#method.offset_from) - /// would compute, but with the added precondition that the offset is - /// guaranteed to be non-negative. This method is equivalent to - /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, - /// but it provides slightly more information to the optimizer, which can - /// sometimes allow it to optimize slightly better with some backends. - /// - /// This method can be thought of as recovering the `count` that was passed - /// to [`add`](#method.add) (or, with the parameters in the other order, - /// to [`sub`](#method.sub)). The following are all equivalent, assuming - /// that their safety preconditions are met: - /// ```rust - /// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe { - /// ptr.offset_from_unsigned(origin) == count - /// # && - /// origin.add(count) == ptr - /// # && - /// ptr.sub(count) == origin - /// # } } - /// ``` - /// - /// # Safety - /// - /// - The distance between the pointers must be non-negative (`self >= origin`) - /// - /// - *All* the safety conditions of [`offset_from`](#method.offset_from) - /// apply to this method as well; see it for the full details. - /// - /// Importantly, despite the return type of this method being able to represent - /// a larger offset, it's still *not permitted* to pass pointers which differ - /// by more than `isize::MAX` *bytes*. As such, the result of this method will - /// always be less than or equal to `isize::MAX as usize`. - /// - /// # Panics - /// - /// This function panics if `T` is a Zero-Sized Type ("ZST"). - /// - /// # Examples - /// - /// ``` - /// let a = [0; 5]; - /// let ptr1: *const i32 = &a[1]; - /// let ptr2: *const i32 = &a[3]; - /// unsafe { - /// assert_eq!(ptr2.offset_from_unsigned(ptr1), 2); - /// assert_eq!(ptr1.add(2), ptr2); - /// assert_eq!(ptr2.sub(2), ptr1); - /// assert_eq!(ptr2.offset_from_unsigned(ptr2), 0); - /// } - /// - /// // This would be incorrect, as the pointers are not correctly ordered: - /// // ptr1.offset_from_unsigned(ptr2) - /// ``` - #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] - #[inline] - #[track_caller] - pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize - where - T: Sized, - { - #[rustc_allow_const_fn_unstable(const_eval_select)] - const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool { - const_eval_select!( - @capture { this: *const (), origin: *const () } -> bool: - if const { - true - } else { - this >= origin - } - ) - } - - ub_checks::assert_unsafe_precondition!( - check_language_ub, - "ptr::offset_from_unsigned requires `self >= origin`", - ( - this: *const () = self as *const (), - origin: *const () = origin as *const (), - ) => runtime_ptr_ge(this, origin) - ); - - let pointee_size = size_of::(); - assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); - // SAFETY: the caller must uphold the safety contract for `ptr_offset_from_unsigned`. - unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } - } - - /// Calculates the distance between two pointers within the same allocation, *where it's known that - /// `self` is equal to or greater than `origin`*. The returned value is in - /// units of **bytes**. - /// - /// This is purely a convenience for casting to a `u8` pointer and - /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it. - /// See that method for documentation and safety requirements. - /// - /// For non-`Sized` pointees this operation considers only the data pointers, - /// ignoring the metadata. - #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] - #[inline] - #[track_caller] - pub const unsafe fn byte_offset_from_unsigned(self, origin: *const U) -> usize { - // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`. - unsafe { self.cast::().offset_from_unsigned(origin.cast::()) } - } /// Returns whether two pointers are guaranteed to be equal. /// @@ -1158,24 +1184,6 @@ impl *const T { self.cast::().wrapping_sub(count).with_metadata_of(self) } - /// Reads the value from `self` without moving it. This leaves the - /// memory in `self` unchanged. - /// - /// See [`ptr::read`] for safety concerns and examples. - /// - /// [`ptr::read`]: crate::ptr::read() - #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] - #[inline] - #[track_caller] - pub const unsafe fn read(self) -> T - where - T: Sized, - { - // SAFETY: the caller must uphold the safety contract for `read`. - unsafe { read(self) } - } - /// Performs a volatile read of the value from `self` without moving it. This /// leaves the memory in `self` unchanged. /// @@ -1571,7 +1579,7 @@ impl *const [T; N] { /// Pointer equality is by address, as produced by the [`<*const T>::addr`](pointer::addr) method. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for *const T { +impl PartialEq for *const T { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &*const T) -> bool { @@ -1581,11 +1589,11 @@ impl PartialEq for *const T { /// Pointer equality is an equivalence relation. #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for *const T {} +impl Eq for *const T {} /// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method. #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for *const T { +impl Ord for *const T { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &*const T) -> Ordering { @@ -1601,7 +1609,7 @@ impl Ord for *const T { /// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for *const T { +impl PartialOrd for *const T { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn partial_cmp(&self, other: &*const T) -> Option { @@ -1634,7 +1642,7 @@ impl PartialOrd for *const T { } #[stable(feature = "raw_ptr_default", since = "1.88.0")] -impl Default for *const T { +impl Default for *const T { /// Returns the default value of [`null()`][crate::ptr::null]. fn default() -> Self { crate::ptr::null() diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index f3faa386355fe..46c6d57fc4dce 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -81,7 +81,7 @@ pub trait Pointee: PointeeSized + ?Forget { /// ``` #[unstable(feature = "ptr_metadata", issue = "81513")] // NOTE: don’t stabilize this before trait aliases are stable in the language? -pub trait Thin = Pointee + PointeeSized; +pub trait Thin = Pointee + PointeeSized + ?Forget; /// Extracts the metadata component of a pointer. /// @@ -112,7 +112,7 @@ pub const fn metadata(ptr: *const T) -> ( +pub const fn from_raw_parts( data_pointer: *const impl Thin, metadata: ::Metadata, ) -> *const T { @@ -125,7 +125,7 @@ pub const fn from_raw_parts( /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] #[inline] -pub const fn from_raw_parts_mut( +pub const fn from_raw_parts_mut( data_pointer: *mut impl Thin, metadata: ::Metadata, ) -> *mut T { @@ -155,7 +155,7 @@ pub const fn from_raw_parts_mut( /// duplicated in multiple codegen units), and pointers to vtables of *different* types/traits can /// compare equal (since identical vtables can be deduplicated within a codegen unit). #[lang = "dyn_metadata"] -pub struct DynMetadata { +pub struct DynMetadata { _vtable_ptr: NonNull, _phantom: crate::marker::PhantomData, } @@ -168,7 +168,7 @@ unsafe extern "C" { type VTable; } -impl DynMetadata { +impl DynMetadata { /// When `DynMetadata` appears as the metadata field of a wide pointer, the rustc_middle layout /// computation does magic and the resulting layout is *not* a `FieldsShape::Aggregate`, instead /// it is a `FieldsShape::Primitive`. This means that the same type can have different layout @@ -209,10 +209,10 @@ impl DynMetadata { } } -unsafe impl Send for DynMetadata {} -unsafe impl Sync for DynMetadata {} +unsafe impl Send for DynMetadata {} +unsafe impl Sync for DynMetadata {} -impl fmt::Debug for DynMetadata { +impl fmt::Debug for DynMetadata { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish() } @@ -220,27 +220,27 @@ impl fmt::Debug for DynMetadata { // Manual impls needed to avoid `Dyn: $Trait` bounds. -impl Unpin for DynMetadata {} +impl Unpin for DynMetadata {} -impl Copy for DynMetadata {} +impl Copy for DynMetadata {} -impl Clone for DynMetadata { +impl Clone for DynMetadata { #[inline] fn clone(&self) -> Self { *self } } -impl Eq for DynMetadata {} +impl Eq for DynMetadata {} -impl PartialEq for DynMetadata { +impl PartialEq for DynMetadata { #[inline] fn eq(&self, other: &Self) -> bool { crate::ptr::eq::(self.vtable_ptr(), other.vtable_ptr()) } } -impl Ord for DynMetadata { +impl Ord for DynMetadata { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &Self) -> crate::cmp::Ordering { @@ -248,7 +248,7 @@ impl Ord for DynMetadata { } } -impl PartialOrd for DynMetadata { +impl PartialOrd for DynMetadata { #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index fd067d19fcd98..41bec296a7436 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -403,7 +403,7 @@ use crate::cmp::Ordering; use crate::intrinsics::const_eval_select; -use crate::marker::{Destruct, FnPtr, PointeeSized}; +use crate::marker::{Destruct, FnPtr, Forget, PointeeSized}; use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::num::NonZero; use crate::{fmt, hash, intrinsics, ub_checks}; @@ -523,7 +523,7 @@ mod mut_ptr; #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] -pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { +pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { ub_checks::assert_unsafe_precondition!( check_language_ub, "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ @@ -620,7 +620,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] -pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { +pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { ub_checks::assert_unsafe_precondition!( @@ -694,7 +694,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] -pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { +pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. unsafe { ub_checks::assert_unsafe_precondition!( @@ -802,7 +802,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { #[allow(unconditional_recursion)] #[rustc_diagnostic_item = "ptr_drop_in_place"] #[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")] -pub const unsafe fn drop_in_place(to_drop: *mut T) +pub const unsafe fn drop_in_place(to_drop: *mut T) where T: [const] Destruct, { @@ -834,7 +834,7 @@ where #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] #[rustc_diagnostic_item = "ptr_null"] -pub const fn null() -> *const T { +pub const fn null() -> *const T { from_raw_parts(without_provenance::<()>(0), ()) } @@ -859,7 +859,7 @@ pub const fn null() -> *const T { #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] #[rustc_diagnostic_item = "ptr_null_mut"] -pub const fn null_mut() -> *mut T { +pub const fn null_mut() -> *mut T { from_raw_parts_mut(without_provenance_mut::<()>(0), ()) } @@ -880,7 +880,7 @@ pub const fn null_mut() -> *mut T { #[must_use] #[stable(feature = "strict_provenance", since = "1.84.0")] #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] -pub const fn without_provenance(addr: usize) -> *const T { +pub const fn without_provenance(addr: usize) -> *const T { without_provenance_mut(addr) } @@ -919,7 +919,7 @@ pub const fn dangling() -> *const T { #[stable(feature = "strict_provenance", since = "1.84.0")] #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] #[allow(integer_to_ptr_transmutes)] // Expected semantics here. -pub const fn without_provenance_mut(addr: usize) -> *mut T { +pub const fn without_provenance_mut(addr: usize) -> *mut T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute // semantics, it relies on sysroot crates having special status. @@ -941,7 +941,7 @@ pub const fn without_provenance_mut(addr: usize) -> *mut T { #[must_use] #[stable(feature = "strict_provenance", since = "1.84.0")] #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] -pub const fn dangling_mut() -> *mut T { +pub const fn dangling_mut() -> *mut T { NonNull::dangling().as_ptr() } @@ -1023,7 +1023,7 @@ pub const fn with_exposed_provenance(addr: usize) -> *const T { #[rustc_const_stable(feature = "const_exposed_provenance", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead -pub const fn with_exposed_provenance_mut(addr: usize) -> *mut T { +pub const fn with_exposed_provenance_mut(addr: usize) -> *mut T { addr as *mut T } @@ -1294,7 +1294,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_swap", since = "1.85.0")] #[rustc_diagnostic_item = "ptr_swap"] -pub const unsafe fn swap(x: *mut T, y: *mut T) { +pub const unsafe fn swap(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. let mut tmp = MaybeUninit::::uninit(); @@ -1573,7 +1573,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, bytes: NonZero(dst: *mut T, src: T) -> T { +pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be // cast to a mutable reference (valid for writes, aligned, initialized), // and cannot overlap `src` since `dst` must point to a distinct @@ -1702,7 +1702,7 @@ pub const unsafe fn replace(dst: *mut T, src: T) -> T { #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] #[track_caller] #[rustc_diagnostic_item = "ptr_read"] -pub const unsafe fn read(src: *const T) -> T { +pub const unsafe fn read(src: *const T) -> T { // It would be semantically correct to implement this via `copy_nonoverlapping` // and `MaybeUninit`, as was done before PR #109035. Calling `assume_init` // provides enough information to know that this is a typed operation. @@ -1820,7 +1820,7 @@ pub const unsafe fn read(src: *const T) -> T { #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] #[track_caller] #[rustc_diagnostic_item = "ptr_read_unaligned"] -pub const unsafe fn read_unaligned(src: *const T) -> T { +pub const unsafe fn read_unaligned(src: *const T) -> T { let mut tmp = MaybeUninit::::uninit(); // SAFETY: the caller must guarantee that `src` is valid for reads. // `src` cannot overlap `tmp` because `tmp` was just allocated on @@ -1918,7 +1918,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write"] #[track_caller] -pub const unsafe fn write(dst: *mut T, src: T) { +pub const unsafe fn write(dst: *mut T, src: T) { // Semantically, it would be fine for this to be implemented as a // `copy_nonoverlapping` and appropriate drop suppression of `src`. @@ -2022,7 +2022,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[track_caller] -pub const unsafe fn write_unaligned(dst: *mut T, src: T) { +pub const unsafe fn write_unaligned(dst: *mut T, src: T) { // SAFETY: the caller must guarantee that `dst` is valid for writes. // `dst` cannot overlap `src` because the caller has mutable access // to `dst` while `src` is owned by this function. @@ -2104,7 +2104,7 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { #[stable(feature = "volatile", since = "1.9.0")] #[track_caller] #[rustc_diagnostic_item = "ptr_read_volatile"] -pub unsafe fn read_volatile(src: *const T) -> T { +pub unsafe fn read_volatile(src: *const T) -> T { // SAFETY: the caller must uphold the safety contract for `volatile_load`. unsafe { ub_checks::assert_unsafe_precondition!( @@ -2191,7 +2191,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { #[stable(feature = "volatile", since = "1.9.0")] #[rustc_diagnostic_item = "ptr_write_volatile"] #[track_caller] -pub unsafe fn write_volatile(dst: *mut T, src: T) { +pub unsafe fn write_volatile(dst: *mut T, src: T) { // SAFETY: the caller must uphold the safety contract for `volatile_store`. unsafe { ub_checks::assert_unsafe_precondition!( @@ -2224,7 +2224,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { /// /// Any questions go to @nagisa. #[allow(ptr_to_integer_transmute_in_consts)] -pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { +pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= // 1, where the method versions of these operations are not inlined. use intrinsics::{ diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 24ee92bdd6e1b..30377e1aceb69 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1,11 +1,11 @@ use super::*; use crate::cmp::Ordering::{Equal, Greater, Less}; use crate::intrinsics::const_eval_select; -use crate::marker::{Destruct, PointeeSized}; +use crate::marker::{Destruct, Forget, PointeeSized}; use crate::mem::{self, SizedTypeProperties}; use crate::slice::{self, SliceIndex}; -impl *mut T { +impl *mut T { #[doc = include_str!("docs/is_null.md")] /// /// # Examples @@ -23,15 +23,6 @@ impl *mut T { self.cast_const().is_null() } - /// Casts to a pointer of another type. - #[stable(feature = "ptr_cast", since = "1.38.0")] - #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] - #[rustc_diagnostic_item = "ptr_cast"] - #[inline(always)] - pub const fn cast(self) -> *mut U { - self as _ - } - /// Try to cast to a pointer of another type by checking alignment. /// /// If the pointer is properly aligned to the target type, it will be @@ -112,7 +103,7 @@ impl *mut T { #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *mut U where - U: PointeeSized, + U: PointeeSized + ?Forget, { from_raw_parts_mut::(self as *mut (), metadata(meta)) } @@ -135,20 +126,6 @@ impl *mut T { self as _ } - #[doc = include_str!("./docs/addr.md")] - /// - /// [without_provenance]: without_provenance_mut - #[must_use] - #[inline(always)] - #[stable(feature = "strict_provenance", since = "1.84.0")] - pub fn addr(self) -> usize { - // A pointer-to-integer transmute currently has exactly the right semantics: it returns the - // address without exposing the provenance. Note that this is *not* a stable guarantee about - // transmute semantics, it relies on sysroot crates having special status. - // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the - // provenance). - unsafe { mem::transmute(self.cast::<()>()) } - } /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in /// [`with_exposed_provenance_mut`] and returns the "address" portion. @@ -214,6 +191,32 @@ impl *mut T { pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } +} + +impl *mut T { + /// Casts to a pointer of another type. + #[stable(feature = "ptr_cast", since = "1.38.0")] + #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] + #[rustc_diagnostic_item = "ptr_cast"] + #[inline(always)] + pub const fn cast(self) -> *mut U { + self as _ + } + + #[doc = include_str!("./docs/addr.md")] + /// + /// [without_provenance]: without_provenance_mut + #[must_use] + #[inline(always)] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn addr(self) -> usize { + // A pointer-to-integer transmute currently has exactly the right semantics: it returns the + // address without exposing the provenance. Note that this is *not* a stable guarantee about + // transmute semantics, it relies on sysroot crates having special status. + // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the + // provenance). + unsafe { mem::transmute(self.cast::<()>()) } + } /// Decompose a (possibly wide) pointer into its data pointer and metadata components. /// @@ -224,6 +227,182 @@ impl *mut T { (self.cast(), super::metadata(self)) } + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from`][pointer::offset_from] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset_from(self, origin: *const U) -> isize { + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { self.cast::().offset_from(origin.cast::()) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it. + /// See that method for documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] + #[inline] + #[track_caller] + pub const unsafe fn byte_offset_from_unsigned(self, origin: *mut U) -> usize { + // SAFETY: the caller must uphold the safety contract for `byte_offset_from_unsigned`. + unsafe { (self as *const T).byte_offset_from_unsigned(origin) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of T: the distance in bytes is divided by `size_of::()`. + /// + /// This computes the same value that [`offset_from`](#method.offset_from) + /// would compute, but with the added precondition that the offset is + /// guaranteed to be non-negative. This method is equivalent to + /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, + /// but it provides slightly more information to the optimizer, which can + /// sometimes allow it to optimize slightly better with some backends. + /// + /// This method can be thought of as recovering the `count` that was passed + /// to [`add`](#method.add) (or, with the parameters in the other order, + /// to [`sub`](#method.sub)). The following are all equivalent, assuming + /// that their safety preconditions are met: + /// ```rust + /// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe { + /// ptr.offset_from_unsigned(origin) == count + /// # && + /// origin.add(count) == ptr + /// # && + /// ptr.sub(count) == origin + /// # } } + /// ``` + /// + /// # Safety + /// + /// - The distance between the pointers must be non-negative (`self >= origin`) + /// + /// - *All* the safety conditions of [`offset_from`](#method.offset_from) + /// apply to this method as well; see it for the full details. + /// + /// Importantly, despite the return type of this method being able to represent + /// a larger offset, it's still *not permitted* to pass pointers which differ + /// by more than `isize::MAX` *bytes*. As such, the result of this method will + /// always be less than or equal to `isize::MAX as usize`. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// ``` + /// let mut a = [0; 5]; + /// let p: *mut i32 = a.as_mut_ptr(); + /// unsafe { + /// let ptr1: *mut i32 = p.add(1); + /// let ptr2: *mut i32 = p.add(3); + /// + /// assert_eq!(ptr2.offset_from_unsigned(ptr1), 2); + /// assert_eq!(ptr1.add(2), ptr2); + /// assert_eq!(ptr2.sub(2), ptr1); + /// assert_eq!(ptr2.offset_from_unsigned(ptr2), 0); + /// } + /// + /// // This would be incorrect, as the pointers are not correctly ordered: + /// // ptr1.offset_from(ptr2) + /// ``` + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] + #[inline] + #[track_caller] + pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`. + unsafe { (self as *const T).offset_from_unsigned(origin) } + } + + /// Returns whether the pointer is properly aligned for `T`. + /// + /// # Examples + /// + /// ``` + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let mut data = AlignedI32(42); + /// let ptr = &mut data as *mut AlignedI32; + /// + /// assert!(ptr.is_aligned()); + /// assert!(!ptr.wrapping_byte_add(1).is_aligned()); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] + pub fn is_aligned(self) -> bool + where + T: Sized, + { + self.is_aligned_to(align_of::()) + } + + /// Returns whether the pointer is aligned to `align`. + /// + /// For non-`Sized` pointees this operation considers only the data pointer, + /// ignoring the metadata. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two (this includes 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(pointer_is_aligned_to)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let mut data = AlignedI32(42); + /// let ptr = &mut data as *mut AlignedI32; + /// + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// + /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2)); + /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4)); + /// + /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8)); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "pointer_is_aligned_to", issue = "96284")] + pub fn is_aligned_to(self, align: usize) -> bool { + if !align.is_power_of_two() { + panic!("is_aligned_to: align is not a power-of-two"); + } + + self.addr() & (align - 1) == 0 + } +} + +impl *mut T { #[doc = include_str!("./docs/as_ref.md")] /// /// ``` @@ -798,113 +977,8 @@ impl *mut T { unsafe { (self as *const T).offset_from(origin) } } - /// Calculates the distance between two pointers within the same allocation. The returned value is in - /// units of **bytes**. - /// - /// This is purely a convenience for casting to a `u8` pointer and - /// using [`offset_from`][pointer::offset_from] on it. See that method for - /// documentation and safety requirements. - /// - /// For non-`Sized` pointees this operation considers only the data pointers, - /// ignoring the metadata. - #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] - #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub const unsafe fn byte_offset_from(self, origin: *const U) -> isize { - // SAFETY: the caller must uphold the safety contract for `offset_from`. - unsafe { self.cast::().offset_from(origin.cast::()) } - } - /// Calculates the distance between two pointers within the same allocation, *where it's known that - /// `self` is equal to or greater than `origin`*. The returned value is in - /// units of T: the distance in bytes is divided by `size_of::()`. - /// - /// This computes the same value that [`offset_from`](#method.offset_from) - /// would compute, but with the added precondition that the offset is - /// guaranteed to be non-negative. This method is equivalent to - /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, - /// but it provides slightly more information to the optimizer, which can - /// sometimes allow it to optimize slightly better with some backends. - /// - /// This method can be thought of as recovering the `count` that was passed - /// to [`add`](#method.add) (or, with the parameters in the other order, - /// to [`sub`](#method.sub)). The following are all equivalent, assuming - /// that their safety preconditions are met: - /// ```rust - /// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe { - /// ptr.offset_from_unsigned(origin) == count - /// # && - /// origin.add(count) == ptr - /// # && - /// ptr.sub(count) == origin - /// # } } - /// ``` - /// - /// # Safety - /// - /// - The distance between the pointers must be non-negative (`self >= origin`) - /// - /// - *All* the safety conditions of [`offset_from`](#method.offset_from) - /// apply to this method as well; see it for the full details. - /// - /// Importantly, despite the return type of this method being able to represent - /// a larger offset, it's still *not permitted* to pass pointers which differ - /// by more than `isize::MAX` *bytes*. As such, the result of this method will - /// always be less than or equal to `isize::MAX as usize`. - /// - /// # Panics - /// - /// This function panics if `T` is a Zero-Sized Type ("ZST"). - /// - /// # Examples - /// - /// ``` - /// let mut a = [0; 5]; - /// let p: *mut i32 = a.as_mut_ptr(); - /// unsafe { - /// let ptr1: *mut i32 = p.add(1); - /// let ptr2: *mut i32 = p.add(3); - /// - /// assert_eq!(ptr2.offset_from_unsigned(ptr1), 2); - /// assert_eq!(ptr1.add(2), ptr2); - /// assert_eq!(ptr2.sub(2), ptr1); - /// assert_eq!(ptr2.offset_from_unsigned(ptr2), 0); - /// } - /// - /// // This would be incorrect, as the pointers are not correctly ordered: - /// // ptr1.offset_from(ptr2) - /// ``` - #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] - #[inline] - #[track_caller] - pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize - where - T: Sized, - { - // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`. - unsafe { (self as *const T).offset_from_unsigned(origin) } - } - /// Calculates the distance between two pointers within the same allocation, *where it's known that - /// `self` is equal to or greater than `origin`*. The returned value is in - /// units of **bytes**. - /// - /// This is purely a convenience for casting to a `u8` pointer and - /// using [`offset_from_unsigned`][pointer::offset_from_unsigned] on it. - /// See that method for documentation and safety requirements. - /// - /// For non-`Sized` pointees this operation considers only the data pointers, - /// ignoring the metadata. - #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] - #[inline] - #[track_caller] - pub const unsafe fn byte_offset_from_unsigned(self, origin: *mut U) -> usize { - // SAFETY: the caller must uphold the safety contract for `byte_offset_from_unsigned`. - unsafe { (self as *const T).byte_offset_from_unsigned(origin) } - } #[doc = include_str!("./docs/add.md")] /// @@ -1577,71 +1651,7 @@ impl *mut T { ret } - /// Returns whether the pointer is properly aligned for `T`. - /// - /// # Examples - /// - /// ``` - /// // On some platforms, the alignment of i32 is less than 4. - /// #[repr(align(4))] - /// struct AlignedI32(i32); - /// - /// let mut data = AlignedI32(42); - /// let ptr = &mut data as *mut AlignedI32; - /// - /// assert!(ptr.is_aligned()); - /// assert!(!ptr.wrapping_byte_add(1).is_aligned()); - /// ``` - #[must_use] - #[inline] - #[stable(feature = "pointer_is_aligned", since = "1.79.0")] - pub fn is_aligned(self) -> bool - where - T: Sized, - { - self.is_aligned_to(align_of::()) - } - - /// Returns whether the pointer is aligned to `align`. - /// - /// For non-`Sized` pointees this operation considers only the data pointer, - /// ignoring the metadata. - /// - /// # Panics - /// - /// The function panics if `align` is not a power-of-two (this includes 0). - /// - /// # Examples - /// - /// ``` - /// #![feature(pointer_is_aligned_to)] - /// - /// // On some platforms, the alignment of i32 is less than 4. - /// #[repr(align(4))] - /// struct AlignedI32(i32); - /// - /// let mut data = AlignedI32(42); - /// let ptr = &mut data as *mut AlignedI32; - /// - /// assert!(ptr.is_aligned_to(1)); - /// assert!(ptr.is_aligned_to(2)); - /// assert!(ptr.is_aligned_to(4)); - /// - /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2)); - /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4)); - /// - /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8)); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "pointer_is_aligned_to", issue = "96284")] - pub fn is_aligned_to(self, align: usize) -> bool { - if !align.is_power_of_two() { - panic!("is_aligned_to: align is not a power-of-two"); - } - self.addr() & (align - 1) == 0 - } } impl *mut T { @@ -1999,7 +2009,7 @@ impl *mut [T; N] { /// Pointer equality is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for *mut T { +impl PartialEq for *mut T { #[inline(always)] #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &*mut T) -> bool { @@ -2009,11 +2019,11 @@ impl PartialEq for *mut T { /// Pointer equality is an equivalence relation. #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for *mut T {} +impl Eq for *mut T {} /// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method. #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for *mut T { +impl Ord for *mut T { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &*mut T) -> Ordering { @@ -2029,7 +2039,7 @@ impl Ord for *mut T { /// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for *mut T { +impl PartialOrd for *mut T { #[inline(always)] #[allow(ambiguous_wide_pointer_comparisons)] fn partial_cmp(&self, other: &*mut T) -> Option { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index bfe2cdf69c6ee..c117fc9dd678f 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1,7 +1,5 @@ -use core::marker::Forget; - use crate::cmp::Ordering; -use crate::marker::{Destruct, PointeeSized, Unsize}; +use crate::marker::{Destruct, Forget, PointeeSized, Unsize}; use crate::mem::{MaybeUninit, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{CoerceUnsized, DispatchFromDyn}; @@ -74,7 +72,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonNull"] -pub struct NonNull { +pub struct NonNull { // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to // this is banned by . pointer: *const T, @@ -83,14 +81,14 @@ pub struct NonNull { /// `NonNull` pointers are not `Send` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Send for NonNull {} +impl !Send for NonNull {} /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Sync for NonNull {} +impl !Sync for NonNull {} -impl NonNull { +impl NonNull { /// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. /// /// For more details, see the equivalent method on a raw pointer, [`ptr::without_provenance_mut`]. @@ -204,7 +202,7 @@ impl NonNull { } } -impl NonNull { +impl NonNull { /// Creates a new `NonNull`. /// /// # Safety @@ -501,7 +499,7 @@ impl NonNull { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub const fn cast(self) -> NonNull { + pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } @@ -529,7 +527,7 @@ impl NonNull { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn try_cast_aligned(self) -> Option> { + pub fn try_cast_aligned(self) -> Option> { if self.is_aligned_to(align_of::()) { Some(self.cast()) } else { None } } @@ -1645,7 +1643,7 @@ impl NonNull<[T]> { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Clone for NonNull { +impl Clone for NonNull { #[inline(always)] fn clone(&self) -> Self { *self @@ -1653,19 +1651,19 @@ impl Clone for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Copy for NonNull {} +impl Copy for NonNull {} #[unstable(feature = "coerce_unsized", issue = "18598")] impl CoerceUnsized> for NonNull where T: Unsize {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl DispatchFromDyn> for NonNull where +impl DispatchFromDyn> for NonNull where T: Unsize { } #[stable(feature = "pin", since = "1.33.0")] -unsafe impl PinCoerceUnsized for NonNull {} +unsafe impl PinCoerceUnsized for NonNull {} #[stable(feature = "nonnull", since = "1.25.0")] impl fmt::Debug for NonNull { @@ -1682,10 +1680,10 @@ impl fmt::Pointer for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Eq for NonNull {} +impl Eq for NonNull {} #[stable(feature = "nonnull", since = "1.25.0")] -impl PartialEq for NonNull { +impl PartialEq for NonNull { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &Self) -> bool { @@ -1694,7 +1692,7 @@ impl PartialEq for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Ord for NonNull { +impl Ord for NonNull { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn cmp(&self, other: &Self) -> Ordering { @@ -1703,7 +1701,7 @@ impl Ord for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl PartialOrd for NonNull { +impl PartialOrd for NonNull { #[inline] #[allow(ambiguous_wide_pointer_comparisons)] fn partial_cmp(&self, other: &Self) -> Option { @@ -1721,7 +1719,7 @@ impl hash::Hash for NonNull { #[unstable(feature = "ptr_internals", issue = "none")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From> for NonNull { +impl const From> for NonNull { #[inline] fn from(unique: Unique) -> Self { unique.as_non_null_ptr() @@ -1730,7 +1728,7 @@ impl const From> for NonNull { #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From<&mut T> for NonNull { +impl const From<&mut T> for NonNull { /// Converts a `&mut T` to a `NonNull`. /// /// This conversion is safe and infallible since references cannot be null. @@ -1742,7 +1740,7 @@ impl const From<&mut T> for NonNull { #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From<&T> for NonNull { +impl const From<&T> for NonNull { /// Converts a `&T` to a `NonNull`. /// /// This conversion is safe and infallible since references cannot be null. diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 117696be148ed..47358fc90700c 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -76,7 +76,7 @@ impl Unique { } #[unstable(feature = "ptr_internals", issue = "none")] -impl Unique { +impl Unique { /// Creates a new `Unique`. /// /// # Safety @@ -147,7 +147,7 @@ impl Unique { /// Casts to a pointer of another type. #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub const fn cast(self) -> Unique { + pub const fn cast(self) -> Unique { // FIXME(const-hack): replace with `From` // SAFETY: is `NonNull` Unique { pointer: self.pointer.cast(), _marker: PhantomData } @@ -155,7 +155,7 @@ impl Unique { } #[unstable(feature = "ptr_internals", issue = "none")] -impl Clone for Unique { +impl Clone for Unique { #[inline] fn clone(&self) -> Self { *self @@ -163,13 +163,13 @@ impl Clone for Unique { } #[unstable(feature = "ptr_internals", issue = "none")] -impl Copy for Unique {} +impl Copy for Unique {} #[unstable(feature = "ptr_internals", issue = "none")] impl CoerceUnsized> for Unique where T: Unsize {} #[unstable(feature = "ptr_internals", issue = "none")] -impl DispatchFromDyn> for Unique where +impl DispatchFromDyn> for Unique where T: Unsize { } @@ -193,7 +193,7 @@ impl fmt::Pointer for Unique { #[unstable(feature = "ptr_internals", issue = "none")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From<&mut T> for Unique { +impl const From<&mut T> for Unique { /// Converts a `&mut T` to a `Unique`. /// /// This conversion is infallible since references cannot be null. @@ -205,7 +205,7 @@ impl const From<&mut T> for Unique { #[unstable(feature = "ptr_internals", issue = "none")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From> for Unique { +impl const From> for Unique { /// Converts a `NonNull` to a `Unique`. /// /// This conversion is infallible since `NonNull` cannot be null. diff --git a/library/core/src/result.rs b/library/core/src/result.rs index c69762a728598..7bcecc66ab7b7 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -534,7 +534,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FusedIterator, TrustedLen}; -use crate::marker::Destruct; +use crate::marker::{Destruct, Forget}; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; @@ -547,7 +547,7 @@ use crate::{convert, fmt, hint}; #[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[rustc_diagnostic_item = "Result"] #[stable(feature = "rust1", since = "1.0.0")] -pub enum Result { +pub enum Result { /// Contains the success value #[lang = "Ok"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1874,7 +1874,7 @@ const fn unwrap_failed(_msg: &str, _error: &T) -> ! { #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Result where - T: Clone, + T: Clone + ?Forget, E: Clone, { #[inline] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 61eb78294f68b..ae25e28a5bebf 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -8,6 +8,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics::{exact_div, unchecked_sub}; +use crate::marker::Forget; use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive}; @@ -96,7 +97,7 @@ enum Direction { Back, } -impl [T] { +impl [T] { /// Returns the number of elements in the slice. /// /// # Examples @@ -134,7 +135,9 @@ impl [T] { pub const fn is_empty(&self) -> bool { self.len() == 0 } +} +impl [T] { /// Returns the first element of the slice, or `None` if it is empty. /// /// # Examples