diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 132f04b05100f..cf56d6c9b59e5 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(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 2be9ba292f976..8e4345e9053c5 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::Forget; 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 + ?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<'_>] +); + #[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 + ?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] +); + #[cfg(any( unix, target_os = "hermit", 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_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_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/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..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/alloc/src/lib.rs b/library/alloc/src/lib.rs index 87ad5b0ce30e6..97e22498a52a7 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(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 49fb21ef5f3ac..9dd46fe8e4375 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(forget_trait)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] 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/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/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/cell.rs b/library/core/src/cell.rs index aeac35e45a5d0..254415d8fb44e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,7 +252,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::{PhantomData, Unsize}; +use crate::marker::{Forget, PhantomData, Unsize}; use crate::mem::{self, ManuallyDrop}; use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::panic::const_panic; @@ -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 + ?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, U> DispatchFromDyn> for UnsafeCell {} +impl + ?Forget, U: ?Forget> 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 + ?Forget, U: ?Forget> DispatchFromDyn> + for SyncUnsafeCell +{ +} #[allow(unused)] fn assert_coerce_unsized( diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 06d2c93cc698f..d9ca0d8374d3c 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: @@ -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..b3455cc384b09 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")] @@ -335,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. @@ -364,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, } @@ -966,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 @@ -1351,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. /// @@ -1500,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 @@ -1853,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 { @@ -2081,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, { @@ -2096,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, { @@ -2139,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, { @@ -2150,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, { @@ -2171,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, { @@ -2214,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, { @@ -2225,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, { @@ -2245,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..6138d173203d0 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; @@ -448,7 +448,7 @@ pub const trait AsMut: PointeeSized { #[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")] @@ -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] @@ -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/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..33e09b69fd862 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 @@ -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; @@ -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/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 cef700be9ea1f..e80cf2283697b 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. /// @@ -835,7 +835,7 @@ pub const 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`. @@ -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. @@ -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. /// @@ -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 @@ -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; @@ -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 @@ -2868,7 +2870,7 @@ pub const fn ptr_metadata + PointeeSized, M>(ptr: #[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 @@ -2879,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 @@ -2890,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/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/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 4b767d8d62218..60f2bafb703c3 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). @@ -157,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. } @@ -175,7 +176,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 +192,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 } @@ -236,7 +237,7 @@ pub trait PointeeSized { #[lang = "unsize"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Unsize: PointeeSized { +pub trait Unsize: PointeeSized + ?Forget { // Empty. } @@ -258,7 +259,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. } @@ -462,7 +463,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. } @@ -486,8 +487,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 +497,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. @@ -517,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. /// @@ -819,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 { @@ -852,10 +853,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,14 +864,14 @@ 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 } } #[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"] @@ -913,7 +914,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 +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 {} @@ -1057,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. /// @@ -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. /// @@ -1341,3 +1342,188 @@ 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 +/// forgotten using [`core::mem::forget`]. +#[lang = "default_trait1"] +#[rustc_unsafe_specialization_marker] +#[unstable(feature = "forget_trait", issue = "none")] +pub unsafe auto trait Forget { + // empty. +} +marker_impls! { + #[unstable(feature = "forget_trait", issue = "none")] + unsafe Forget for + {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 {} + +/// 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/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 334a4b7119a11..781c17785e774 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,24 @@ 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 } + } + +} + +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 } } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 8d666e9b130c0..1d6c0431ba9b8 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,85 +305,13 @@ 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) } } - /// 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`. /// @@ -472,156 +400,13 @@ 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 - /// 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. @@ -793,37 +578,261 @@ impl MaybeUninit { } } - /// Gets a mutable (unique) reference to the contained value. - /// - /// This can be useful when we want to access a `MaybeUninit` that has been - /// initialized but don't have ownership of the `MaybeUninit` (preventing the use - /// of `.assume_init()`). - /// - /// # Safety + + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// - /// Calling this when the content is not yet fully initialized causes undefined - /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really - /// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to - /// initialize a `MaybeUninit`. + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. /// /// # Examples /// - /// ### Correct usage of this method: - /// - /// ```rust - /// # #![allow(unexpected_cfgs)] + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] /// use std::mem::MaybeUninit; /// - /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { unsafe { *buf = [0; 1024] } } - /// # #[cfg(FALSE)] - /// extern "C" { - /// /// Initializes *all* the bytes of the input buffer. - /// fn initialize_buffer(buf: *mut [u8; 1024]); - /// } - /// - /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); - /// - /// // Initialize `buf`: + /// 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) } } + } + + /// 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 + /// initialized but don't have ownership of the `MaybeUninit` (preventing the use + /// of `.assume_init()`). + /// + /// # Safety + /// + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really + /// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to + /// initialize a `MaybeUninit`. + /// + /// # Examples + /// + /// ### Correct usage of this method: + /// + /// ```rust + /// # #![allow(unexpected_cfgs)] + /// use std::mem::MaybeUninit; + /// + /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { unsafe { *buf = [0; 1024] } } + /// # #[cfg(FALSE)] + /// extern "C" { + /// /// Initializes *all* the bytes of the input buffer. + /// fn initialize_buffer(buf: *mut [u8; 1024]); + /// } + /// + /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); + /// + /// // Initialize `buf`: /// unsafe { initialize_buffer(buf.as_mut_ptr()); } /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. /// // However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes. @@ -910,6 +919,105 @@ impl MaybeUninit { } } + /// Unchecked version of [`MaybeUninit::write`] where `T` might not implement [`Forget`]. + /// + /// # Safety + /// + /// 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 + /// + /// 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 + } + /// Extracts the values from an array of `MaybeUninit` containers. /// /// # Safety @@ -949,79 +1057,6 @@ impl MaybeUninit { 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] { @@ -1071,7 +1106,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 +1169,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 +1223,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 +1257,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 +1334,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..d1c5cee543d0e 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. @@ -332,7 +354,7 @@ pub fn forget_unsized(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::() } @@ -415,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) } } @@ -487,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::() } @@ -554,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) } } @@ -874,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. @@ -1230,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. /// @@ -1277,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/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 305861ea7b698..747320f349706 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`. /// @@ -136,12 +136,12 @@ use crate::marker::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: @@ -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 {} 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/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/ops/unsize.rs b/library/core/src/ops/unsize.rs index f0781ee01fd53..dd8d6d279043e 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::{Forget, PointeeSized, Unsize}; /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. @@ -33,40 +33,55 @@ use crate::marker::{PointeeSized, Unsize}; /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "18598")] #[lang = "coerce_unsized"] -pub trait CoerceUnsized { +pub trait CoerceUnsized: ?Forget { // Empty. } // &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 + ?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 + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {} +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 + 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 + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {} +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 + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {} +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 + 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. @@ -116,19 +131,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: ?Forget { // 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 + ?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 + Unsize, U: PointeeSized> 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> DispatchFromDyn<*const U> for *const T {} +impl, U: PointeeSized + ?Forget> 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 + ?Forget> DispatchFromDyn<*mut U> + for *mut T +{ +} diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 430ee3470ac3f..1367a28f84c90 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 @@ -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/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 722af55103839..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 81c2dabf0d1d8..50dacd1538da5 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::{ @@ -1091,7 +1092,7 @@ pub use self::unsafe_pinned::UnsafePinned; #[repr(transparent)] #[rustc_pub_transparent] #[derive(Copy, Clone)] -pub struct Pin { +pub struct Pin { pointer: Ptr, } @@ -1214,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`]. /// @@ -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; } @@ -1821,7 +1824,7 @@ where impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn + PinCoerceUnsized, - U: PinCoerceUnsized, + U: PinCoerceUnsized + ?crate::marker::Forget, { } @@ -1844,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/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs index ae03809b4581f..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::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> DispatchFromDyn> for UnsafePinned {} +impl, U: ?Forget> DispatchFromDyn> for UnsafePinned {} // FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned? 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 451092709443b..45ae30a0e029c 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1,10 +1,11 @@ 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}; -impl *const T { +impl *const T { #[doc = include_str!("docs/is_null.md")] /// /// # Examples @@ -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 @@ -129,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)) } @@ -146,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)] @@ -187,6 +191,120 @@ impl *const T { 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 { /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of /// `self`. /// @@ -223,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`]. @@ -233,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")] /// /// ``` @@ -637,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. /// @@ -1153,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. /// @@ -1566,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 { @@ -1576,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 { @@ -1596,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 { @@ -1629,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 dc3ec3fd19945..46c6d57fc4dce 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` @@ -81,7 +81,7 @@ pub trait Pointee: PointeeSized { /// ``` #[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. /// @@ -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) } @@ -112,7 +112,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadat /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] #[inline] -pub const fn from_raw_parts( +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 a762e969b52dc..c117fc9dd678f 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1,5 +1,5 @@ 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}; @@ -72,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, @@ -81,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`]. @@ -202,7 +202,7 @@ impl NonNull { } } -impl NonNull { +impl NonNull { /// Creates a new `NonNull`. /// /// # Safety @@ -499,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 } } } @@ -527,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 } } @@ -1643,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 @@ -1651,16 +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 T: Unsize {} +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 { @@ -1677,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 { @@ -1689,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 { @@ -1698,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 { @@ -1716,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() @@ -1725,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. @@ -1737,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 cdc8b6cc936df..47358fc90700c 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::{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`. @@ -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,16 @@ 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 T: Unsize {} +impl DispatchFromDyn> for Unique where + T: Unsize +{ +} #[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] unsafe impl PinCoerceUnsized for Unique {} @@ -190,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. @@ -202,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 diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index c2dc3a99ab109..bffbd930752fd 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(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 60c8f53a0cc40..32a9297045176 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(forget_trait)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)]