diff options
Diffstat (limited to 'library/core/src')
40 files changed, 778 insertions, 615 deletions
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index e6f39db9dce..17f4d68867e 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -178,7 +178,7 @@ impl Layout { /// allocate backing structure for `T` (which could be a trait /// or other unsized type like a slice). #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")] #[must_use] #[inline] pub const fn for_value<T: ?Sized>(t: &T) -> Self { @@ -233,8 +233,7 @@ impl Layout { #[must_use] #[inline] pub const fn dangling(&self) -> NonNull<u8> { - // SAFETY: align is guaranteed to be non-zero - unsafe { NonNull::new_unchecked(crate::ptr::without_provenance_mut::<u8>(self.align())) } + NonNull::without_provenance(self.align.as_nonzero()) } /// Creates a layout describing the record that can hold a value @@ -252,7 +251,7 @@ impl Layout { /// Returns an error if the combination of `self.size()` and the given /// `align` violates the conditions listed in [`Layout::from_size_align`]. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")] #[inline] pub const fn align_to(&self, align: usize) -> Result<Self, LayoutError> { if let Some(align) = Alignment::new(align) { @@ -327,7 +326,7 @@ impl Layout { /// This is equivalent to adding the result of `padding_needed_for` /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")] #[must_use = "this returns a new `Layout`, \ without modifying the original"] #[inline] @@ -426,7 +425,7 @@ impl Layout { /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16]))); /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")] #[inline] pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { let new_align = Alignment::max(self.align, next.align); @@ -489,7 +488,7 @@ impl Layout { /// On arithmetic overflow or when the total size would exceed /// `isize::MAX`, returns `LayoutError`. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")] #[inline] pub const fn array<T>(n: usize) -> Result<Self, LayoutError> { // Reduce the amount of code we need to monomorphize per `T`. diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 95d88c7f679..cb130f60cec 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -65,7 +65,6 @@ pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))? // When stabilizing this, update the comment on `core::intrinsics::breakpoint`. #[unstable(feature = "breakpoint", issue = "133724")] #[inline(always)] -#[cfg(not(bootstrap))] pub fn breakpoint() { core::intrinsics::breakpoint(); } diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 9ce0eb61e08..1edade41597 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -214,7 +214,7 @@ impl<T, const N: usize> IntoIter<T, N> { // SAFETY: We know that all elements within `alive` are properly initialized. unsafe { let slice = self.data.get_unchecked(self.alive.clone()); - MaybeUninit::slice_assume_init_ref(slice) + slice.assume_init_ref() } } @@ -224,7 +224,7 @@ impl<T, const N: usize> IntoIter<T, N> { // SAFETY: We know that all elements within `alive` are properly initialized. unsafe { let slice = self.data.get_unchecked_mut(self.alive.clone()); - MaybeUninit::slice_assume_init_mut(slice) + slice.assume_init_mut() } } } @@ -285,7 +285,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> { // SAFETY: These elements are currently initialized, so it's fine to drop them. unsafe { let slice = self.data.get_unchecked_mut(range_to_drop); - ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + slice.assume_init_drop(); } NonZero::new(remaining).map_or(Ok(()), Err) @@ -340,7 +340,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> { // SAFETY: These elements are currently initialized, so it's fine to drop them. unsafe { let slice = self.data.get_unchecked_mut(range_to_drop); - ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + slice.assume_init_drop(); } NonZero::new(remaining).map_or(Ok(()), Err) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 95c1eb460cd..2ae5ded1fd5 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -911,9 +911,7 @@ impl<T> Drop for Guard<'_, T> { // SAFETY: this slice will contain only initialized objects. unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - self.array_mut.get_unchecked_mut(..self.initialized), - )); + self.array_mut.get_unchecked_mut(..self.initialized).assume_init_drop(); } } } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c2c78dd9c67..a033b8bd305 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -596,7 +596,7 @@ impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the /// Arguments structure. #[inline] - pub fn new_v1<const P: usize, const A: usize>( + pub const fn new_v1<const P: usize, const A: usize>( pieces: &'a [&'static str; P], args: &'a [rt::Argument<'a>; A], ) -> Arguments<'a> { @@ -612,7 +612,7 @@ impl<'a> Arguments<'a> { /// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`. /// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`. #[inline] - pub fn new_v1_formatted( + pub const fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [rt::Argument<'a>], fmt: &'a [rt::Placeholder], diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 94341a4da66..85d089a0790 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -96,12 +96,12 @@ pub struct Argument<'a> { #[rustc_diagnostic_item = "ArgumentMethods"] impl Argument<'_> { #[inline] - fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> { + const fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> { Argument { // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and // a `fn(&T, ...)`, so the invariant is maintained. ty: ArgumentType::Placeholder { - value: NonNull::from(x).cast(), + value: NonNull::from_ref(x).cast(), // SAFETY: function pointers always have the same layout. formatter: unsafe { mem::transmute(f) }, _lifetime: PhantomData, @@ -150,7 +150,7 @@ impl Argument<'_> { Self::new(x, UpperExp::fmt) } #[inline] - pub fn from_usize(x: &usize) -> Argument<'_> { + pub const fn from_usize(x: &usize) -> Argument<'_> { Argument { ty: ArgumentType::Count(*x) } } @@ -181,7 +181,7 @@ impl Argument<'_> { } #[inline] - pub(super) fn as_usize(&self) -> Option<usize> { + pub(super) const fn as_usize(&self) -> Option<usize> { match self.ty { ArgumentType::Count(count) => Some(count), ArgumentType::Placeholder { .. } => None, @@ -199,7 +199,7 @@ impl Argument<'_> { /// println!("{f}"); /// ``` #[inline] - pub fn none() -> [Self; 0] { + pub const fn none() -> [Self; 0] { [] } } @@ -216,7 +216,7 @@ impl UnsafeArg { /// See documentation where `UnsafeArg` is required to know when it is safe to /// create and use `UnsafeArg`. #[inline] - pub unsafe fn new() -> Self { + pub const unsafe fn new() -> Self { Self { _private: () } } } diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs index ea6d3b800e6..f1778a4d782 100644 --- a/library/core/src/future/async_drop.rs +++ b/library/core/src/future/async_drop.rs @@ -133,9 +133,8 @@ pub trait AsyncDrop { } #[lang = "async_destruct"] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] trait AsyncDestruct { type AsyncDestructor: Future<Output = ()>; } diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 84bbf985e8b..7a6630c82d0 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -752,11 +752,8 @@ pub struct BuildHasherDefault<H>(marker::PhantomData<fn() -> H>); impl<H> BuildHasherDefault<H> { /// Creates a new BuildHasherDefault for Hasher `H`. - #[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable( - feature = "build_hasher_default_const_new", - since = "CURRENT_RUSTC_VERSION" - )] + #[stable(feature = "build_hasher_default_const_new", since = "1.85.0")] + #[rustc_const_stable(feature = "build_hasher_default_const_new", since = "1.85.0")] pub const fn new() -> Self { BuildHasherDefault(marker::PhantomData) } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 7d44ea7a66b..7b31bbec754 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1382,22 +1382,10 @@ pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] -#[cfg(not(bootstrap))] pub fn breakpoint() { unreachable!() } -/// Executes a breakpoint trap, for inspection by a debugger. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -#[cfg(bootstrap)] -pub unsafe fn breakpoint() { - unreachable!() -} - /// Magic intrinsic that derives its meaning from attributes /// attached to the function. /// @@ -3323,8 +3311,8 @@ pub const fn mul_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_const_unstable(feature = "const_carrying_mul_add", issue = "85532")] #[rustc_nounwind] -#[cfg_attr(not(bootstrap), rustc_intrinsic)] -#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)] +#[rustc_intrinsic] +#[miri::intrinsic_fallback_is_spec] pub const fn carrying_mul_add<T: ~const fallback::CarryingMulAdd<Unsigned = U>, U>( multiplier: T, multiplicand: T, @@ -3969,21 +3957,6 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool { false } -#[rustc_nounwind] -#[inline] -#[rustc_intrinsic] -#[rustc_intrinsic_const_stable_indirect] -#[rustc_allow_const_fn_unstable(const_swap_nonoverlapping)] // this is anyway not called since CTFE implements the intrinsic -#[cfg(bootstrap)] -pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { - // SAFETY: The caller provided single non-overlapping items behind - // pointers, so swapping them with `count: 1` is fine. - unsafe { ptr::swap_nonoverlapping(x, y, 1) }; -} - -#[cfg(bootstrap)] -pub use typed_swap as typed_swap_nonoverlapping; - /// Non-overlapping *typed* swap of a single value. /// /// The codegen backends will replace this with a better implementation when @@ -3999,7 +3972,6 @@ pub use typed_swap as typed_swap_nonoverlapping; #[rustc_intrinsic] #[rustc_intrinsic_const_stable_indirect] #[rustc_allow_const_fn_unstable(const_swap_nonoverlapping)] // this is anyway not called since CTFE implements the intrinsic -#[cfg(not(bootstrap))] pub const unsafe fn typed_swap_nonoverlapping<T>(x: *mut T, y: *mut T) { // SAFETY: The caller provided single non-overlapping items behind // pointers, so swapping them with `count: 1` is fine. diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index f80a60d471c..d03d801b936 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -623,7 +623,6 @@ extern "rust-intrinsic" { /// and others do not. /// /// `T` must be a vector of floats. - #[cfg(not(bootstrap))] #[rustc_nounwind] pub fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T; diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index 4227e503ba7..f86abf7f1e9 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -94,7 +94,7 @@ impl<'data> BorrowedBuf<'data> { // SAFETY: We only slice the filled part of the buffer, which is always valid unsafe { let buf = self.buf.get_unchecked(..self.filled); - MaybeUninit::slice_assume_init_ref(buf) + buf.assume_init_ref() } } @@ -104,7 +104,7 @@ impl<'data> BorrowedBuf<'data> { // SAFETY: We only slice the filled part of the buffer, which is always valid unsafe { let buf = self.buf.get_unchecked_mut(..self.filled); - MaybeUninit::slice_assume_init_mut(buf) + buf.assume_init_mut() } } @@ -114,7 +114,7 @@ impl<'data> BorrowedBuf<'data> { // SAFETY: We only slice the filled part of the buffer, which is always valid unsafe { let buf = self.buf.get_unchecked(..self.filled); - MaybeUninit::slice_assume_init_ref(buf) + buf.assume_init_ref() } } @@ -124,7 +124,7 @@ impl<'data> BorrowedBuf<'data> { // SAFETY: We only slice the filled part of the buffer, which is always valid unsafe { let buf = self.buf.get_unchecked_mut(..self.filled); - MaybeUninit::slice_assume_init_mut(buf) + buf.assume_init_mut() } } @@ -233,7 +233,7 @@ impl<'a> BorrowedCursor<'a> { // SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { let buf = self.buf.buf.get_unchecked(self.buf.filled..self.buf.init); - MaybeUninit::slice_assume_init_ref(buf) + buf.assume_init_ref() } } @@ -243,7 +243,7 @@ impl<'a> BorrowedCursor<'a> { // SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { let buf = self.buf.buf.get_unchecked_mut(self.buf.filled..self.buf.init); - MaybeUninit::slice_assume_init_mut(buf) + buf.assume_init_mut() } } @@ -344,7 +344,7 @@ impl<'a> BorrowedCursor<'a> { // SAFETY: we do not de-initialize any of the elements of the slice unsafe { - MaybeUninit::copy_from_slice(&mut self.as_mut()[..buf.len()], buf); + self.as_mut()[..buf.len()].write_copy_of_slice(buf); } // SAFETY: We just added the entire contents of buf to the filled section. diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index cc64ceb13f7..24ec6b1741c 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -81,9 +81,7 @@ where if const { crate::mem::needs_drop::<T>() } { // SAFETY: self.initialized is always <= N, which also is the length of the array. unsafe { - core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - self.array.get_unchecked_mut(..self.initialized), - )); + self.array.get_unchecked_mut(..self.initialized).assume_init_drop(); } } } diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 73e6d931060..97bb21c8a36 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -472,7 +472,7 @@ macro_rules! spec_tuple_impl { #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for \ 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in \ - CURRENT_RUSTC_VERSION."] + 1.85.0."] => ($ty_name, $var_name, $extend_ty_name, $cnt), ); }; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e31957a1fa7..e845bb34426 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,7 +107,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(do_not_recommend))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(bigint_helper_methods)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 29fc01d37fe..4af9b666e54 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -141,9 +141,8 @@ unsafe impl<T: Sync + ?Sized> Send for &T {} )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable #[rustc_specialization_trait] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] #[rustc_coinductive] pub trait Sized { // Empty. @@ -183,33 +182,27 @@ pub trait Sized { /// [^1]: Formerly known as *object safe*. #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] pub trait Unsize<T: ?Sized> { // Empty. } /// Required trait for constants used in pattern matches. /// -/// Any type that derives `PartialEq` automatically implements this trait, -/// *regardless* of whether its type-parameters implement `PartialEq`. +/// Constants are only allowed as patterns if (a) their type implements +/// `PartialEq`, and (b) interpreting the value of the constant as a pattern +/// is equialent to calling `PartialEq`. This ensures that constants used as +/// patterns cannot expose implementation details in an unexpected way or +/// cause semver hazards. /// -/// If a `const` item contains some type that does not implement this trait, -/// then that type either (1.) does not implement `PartialEq` (which means the -/// constant will not provide that comparison method, which code generation -/// assumes is available), or (2.) it implements *its own* version of -/// `PartialEq` (which we assume does not conform to a structural-equality -/// comparison). +/// This trait ensures point (b). +/// Any type that derives `PartialEq` automatically implements this trait. /// -/// In either of the two scenarios above, we reject usage of such a constant in -/// a pattern match. -/// -/// See also the [structural match RFC][RFC1445], and [issue 63438] which -/// motivated migrating from an attribute-based design to this trait. -/// -/// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md -/// [issue 63438]: https://github.com/rust-lang/rust/issues/63438 +/// Implementing this trait (which is unstable) is a way for type authors to explicitly allow +/// comparing const values of this type; that operation will recursively compare all fields +/// (including private fields), even if that behavior differs from `PartialEq`. This can make it +/// semver-breaking to add further private fields to a type. #[unstable(feature = "structural_match", issue = "31434")] #[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] #[lang = "structural_peq"] @@ -819,9 +812,8 @@ impl<T: ?Sized> StructuralPartialEq for PhantomData<T> {} reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead" )] #[lang = "discriminant_kind"] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] pub trait DiscriminantKind { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. @@ -962,10 +954,9 @@ marker_impls! { #[unstable(feature = "const_destruct", issue = "133214")] #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] -#[cfg_attr(not(bootstrap), const_trait)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] +#[const_trait] pub trait Destruct {} /// A marker for tuple types. @@ -975,9 +966,8 @@ pub trait Destruct {} #[unstable(feature = "tuple_trait", issue = "none")] #[lang = "tuple_trait"] #[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] pub trait Tuple {} /// A marker for pointer-like types. @@ -996,10 +986,9 @@ pub trait Tuple {} message = "`{Self}` needs to have the same ABI as a pointer", label = "`{Self}` needs to be a pointer-like type" )] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_do_not_implement_via_object] pub trait PointerLike {} -#[cfg(not(bootstrap))] marker_impls! { #[unstable(feature = "pointer_like_trait", issue = "none")] PointerLike for @@ -1086,9 +1075,8 @@ marker_impls! { reason = "internal trait for implementing various traits for all function pointers" )] #[lang = "fn_ptr_trait"] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] pub trait FnPtr: Copy + Clone { /// Returns the address of the function pointer. #[lang = "fn_ptr_addr"] @@ -1099,7 +1087,6 @@ pub trait FnPtr: Copy + Clone { #[rustc_builtin_macro(CoercePointee, attributes(pointee))] #[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)] #[unstable(feature = "derive_coerce_pointee", issue = "123430")] -#[cfg(not(bootstrap))] pub macro CoercePointee($item:item) { /* compiler built-in */ } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 58fb5be5812..ac5307a671d 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::mem::{self, ManuallyDrop}; +use crate::mem::ManuallyDrop; use crate::{fmt, intrinsics, ptr, slice}; /// A wrapper type to construct uninitialized instances of `T`. @@ -354,7 +354,7 @@ impl<T> MaybeUninit<T> { /// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] { /// unsafe { /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); - /// MaybeUninit::slice_assume_init_ref(&buf[..len]) + /// buf[..len].assume_init_ref() /// } /// } /// @@ -507,7 +507,7 @@ impl<T> MaybeUninit<T> { /// ``` #[inline(always)] #[stable(feature = "maybe_uninit_write", since = "1.55.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_write", since = "CURRENT_RUSTC_VERSION")] + #[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. @@ -740,7 +740,7 @@ impl<T> MaybeUninit<T> { /// /// On top of that, all additional invariants of the type `T` must be /// satisfied, as the `Drop` implementation of `T` (or its members) may - /// rely on this. For example, setting a [`Vec<T>`] to an invalid but + /// rely on this. For example, setting a `Vec<T>` to an invalid but /// non-null address makes it 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 @@ -748,7 +748,6 @@ impl<T> MaybeUninit<T> { /// behavior. /// /// [`assume_init`]: MaybeUninit::assume_init - /// [`Vec<T>`]: ../../std/vec/struct.Vec.html #[stable(feature = "maybe_uninit_extra", since = "1.60.0")] pub unsafe fn assume_init_drop(&mut self) { // SAFETY: the caller must guarantee that `self` is initialized and @@ -982,44 +981,87 @@ impl<T> MaybeUninit<T> { } } - /// Assuming all the elements are initialized, get a slice to them. + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// - /// # Safety + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. /// - /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements - /// really are in an initialized state. - /// Calling this when the content is not yet fully initialized causes undefined behavior. + /// # Examples /// - /// See [`assume_init_ref`] for more details and examples. + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; /// - /// [`assume_init_ref`]: MaybeUninit::assume_init_ref - #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[inline(always)] - pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] { - // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that - // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. - // The pointer obtained is valid since it refers to memory owned by `slice` which is a - // reference and thus guaranteed to be valid for reads. - unsafe { &*(slice as *const [Self] as *const [T]) } + /// 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<u8>] { + // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes + unsafe { + slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of::<T>()) + } } - /// Assuming all the elements are initialized, get a mutable slice to them. + /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized + /// bytes. /// - /// # Safety + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. /// - /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements - /// really are in an initialized state. - /// Calling this when the content is not yet fully initialized causes undefined behavior. + /// # Examples /// - /// See [`assume_init_mut`] for more details and examples. + /// ``` + /// #![feature(maybe_uninit_as_bytes)] + /// use std::mem::MaybeUninit; /// - /// [`assume_init_mut`]: MaybeUninit::assume_init_mut + /// 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<u8>] { + // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().cast::<MaybeUninit<u8>>(), + super::size_of::<T>(), + ) + } + } + + /// Deprecated version of [`slice::assume_init_ref`]. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[inline(always)] + #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[deprecated( + note = "replaced by inherent assume_init_ref method; will eventually be removed", + since = "1.83.0" + )] + pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] { + // SAFETY: Same for both methods. + unsafe { slice.assume_init_ref() } + } + + /// Deprecated version of [`slice::assume_init_mut`]. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[deprecated( + note = "replaced by inherent assume_init_mut method; will eventually be removed", + since = "1.83.0" + )] pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { - // SAFETY: similar to safety notes for `slice_get_ref`, but we have a - // mutable reference which is also guaranteed to be valid for writes. - unsafe { &mut *(slice as *mut [Self] as *mut [T]) } + // SAFETY: Same for both methods. + unsafe { slice.assume_init_mut() } } /// Gets a pointer to the first element of the array. @@ -1036,142 +1078,34 @@ impl<T> MaybeUninit<T> { this.as_mut_ptr() as *mut T } - /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. - /// - /// If `T` does not implement `Copy`, use [`clone_from_slice`] - /// - /// This is similar to [`slice::copy_from_slice`]. - /// - /// # Panics - /// - /// This function will panic if the two slices have different lengths. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_write_slice)] - /// use std::mem::MaybeUninit; - /// - /// let mut dst = [MaybeUninit::uninit(); 32]; - /// let src = [0; 32]; - /// - /// let init = MaybeUninit::copy_from_slice(&mut dst, &src); - /// - /// assert_eq!(init, src); - /// ``` - /// - /// ``` - /// #![feature(maybe_uninit_write_slice)] - /// use std::mem::MaybeUninit; - /// - /// let mut vec = Vec::with_capacity(32); - /// let src = [0; 16]; - /// - /// MaybeUninit::copy_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src); - /// - /// // SAFETY: we have just copied all the elements of len into the spare capacity - /// // the first src.len() elements of the vec are valid now. - /// unsafe { - /// vec.set_len(src.len()); - /// } - /// - /// assert_eq!(vec, src); - /// ``` - /// - /// [`clone_from_slice`]: MaybeUninit::clone_from_slice + /// Deprecated version of [`slice::write_copy_of_slice`]. #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + #[deprecated( + note = "replaced by inherent write_copy_of_slice method; will eventually be removed", + since = "1.83.0" + )] pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] where T: Copy, { - // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout - let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) }; - - this.copy_from_slice(uninit_src); - - // SAFETY: Valid elements have just been copied into `this` so it is initialized - unsafe { MaybeUninit::slice_assume_init_mut(this) } + this.write_copy_of_slice(src) } - /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. - /// Any already initialized elements will not be dropped. - /// - /// If `T` implements `Copy`, use [`copy_from_slice`] - /// - /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements. - /// - /// # Panics - /// - /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics. - /// - /// If there is a panic, the already cloned elements will be dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_write_slice)] - /// use std::mem::MaybeUninit; - /// - /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; - /// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()]; - /// - /// let init = MaybeUninit::clone_from_slice(&mut dst, &src); - /// - /// assert_eq!(init, src); - /// # // Prevent leaks for Miri - /// # unsafe { std::ptr::drop_in_place(init); } - /// ``` - /// - /// ``` - /// #![feature(maybe_uninit_write_slice)] - /// use std::mem::MaybeUninit; - /// - /// let mut vec = Vec::with_capacity(32); - /// let src = ["rust", "is", "a", "pretty", "cool", "language"]; - /// - /// MaybeUninit::clone_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src); - /// - /// // SAFETY: we have just cloned all the elements of len into the spare capacity - /// // the first src.len() elements of the vec are valid now. - /// unsafe { - /// vec.set_len(src.len()); - /// } - /// - /// assert_eq!(vec, src); - /// ``` - /// - /// [`copy_from_slice`]: MaybeUninit::copy_from_slice + /// Deprecated version of [`slice::write_clone_of_slice`]. #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + #[deprecated( + note = "replaced by inherent write_clone_of_slice method; will eventually be removed", + since = "1.83.0" + )] pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T] where T: Clone, { - // unlike copy_from_slice this does not call clone_from_slice on the slice - // this is because `MaybeUninit<T: Clone>` does not implement Clone. - - assert_eq!(this.len(), src.len(), "destination and source slices have different lengths"); - // NOTE: We need to explicitly slice them to the same length - // for bounds checking to be elided, and the optimizer will - // generate memcpy for simple cases (for example T = u8). - let len = this.len(); - let src = &src[..len]; - - // guard is needed b/c panic might happen during a clone - let mut guard = Guard { slice: this, initialized: 0 }; - - for i in 0..len { - guard.slice[i].write(src[i].clone()); - guard.initialized += 1; - } - - super::forget(guard); - - // SAFETY: Valid elements have just been written into `this` so it is initialized - unsafe { MaybeUninit::slice_assume_init_mut(this) } + this.write_clone_of_slice(src) } - /// Fills `this` with elements by cloning `value`, returning a mutable reference to the now - /// initialized contents of `this`. + /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of the slice. /// Any previously initialized elements will not be dropped. /// /// This is similar to [`slice::fill`]. @@ -1185,27 +1119,26 @@ impl<T> MaybeUninit<T> { /// /// # Examples /// - /// Fill an uninit vec with 1. /// ``` /// #![feature(maybe_uninit_fill)] /// use std::mem::MaybeUninit; /// - /// let mut buf = vec![MaybeUninit::uninit(); 10]; - /// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1); + /// let mut buf = [const { MaybeUninit::uninit() }; 10]; + /// let initialized = MaybeUninit::fill(&mut buf, 1); /// assert_eq!(initialized, &mut [1; 10]); /// ``` #[doc(alias = "memset")] #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T] + pub fn fill(this: &mut [MaybeUninit<T>], value: T) -> &mut [T] where T: Clone, { SpecFill::spec_fill(this, value); // SAFETY: Valid elements have just been filled into `this` so it is initialized - unsafe { MaybeUninit::slice_assume_init_mut(this) } + unsafe { this.assume_init_mut() } } - /// Fills `this` with elements returned by calling a closure repeatedly. + /// Fills a slice with elements returned by calling a closure repeatedly. /// /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can @@ -1220,17 +1153,16 @@ impl<T> MaybeUninit<T> { /// /// # Examples /// - /// Fill an uninit vec with the default value. /// ``` /// #![feature(maybe_uninit_fill)] /// use std::mem::MaybeUninit; /// - /// let mut buf = vec![MaybeUninit::<i32>::uninit(); 10]; - /// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default); + /// let mut buf = [const { MaybeUninit::<i32>::uninit() }; 10]; + /// let initialized = MaybeUninit::fill_with(&mut buf, Default::default); /// assert_eq!(initialized, &mut [0; 10]); /// ``` #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T] + pub fn fill_with<F>(this: &mut [MaybeUninit<T>], mut f: F) -> &mut [T] where F: FnMut() -> T, { @@ -1244,13 +1176,13 @@ impl<T> MaybeUninit<T> { super::forget(guard); // SAFETY: Valid elements have just been written into `this` so it is initialized - unsafe { MaybeUninit::slice_assume_init_mut(this) } + unsafe { this.assume_init_mut() } } - /// Fills `this` with elements yielded by an iterator until either all elements have been + /// Fills a slice with elements yielded by an iterator until either all elements have been /// initialized or the iterator is empty. /// - /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// Returns two slices. The first slice contains the initialized portion of the original slice. /// The second slice is the still-uninitialized remainder of the original slice. /// /// # Panics @@ -1262,37 +1194,51 @@ impl<T> MaybeUninit<T> { /// /// # Examples /// - /// Fill an uninit vec with a cycling iterator. + /// Completely filling the slice: + /// /// ``` /// #![feature(maybe_uninit_fill)] /// use std::mem::MaybeUninit; /// - /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; /// /// let iter = [1, 2, 3].into_iter().cycle(); /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); /// /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); - /// assert_eq!(0, remainder.len()); + /// assert_eq!(remainder.len(), 0); /// ``` /// - /// Fill an uninit vec, but not completely. + /// Partially filling the slice: + /// /// ``` /// #![feature(maybe_uninit_fill)] /// use std::mem::MaybeUninit; /// - /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; /// let iter = [1, 2]; /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); /// /// assert_eq!(initialized, &mut [1, 2]); /// assert_eq!(remainder.len(), 3); /// ``` + /// + /// Checking an iterator after filling a slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 3]; + /// let mut iter = [1, 2, 3, 4, 5].into_iter(); + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter.by_ref()); + /// + /// assert_eq!(initialized, &mut [1, 2, 3]); + /// assert_eq!(remainder.len(), 0); + /// assert_eq!(iter.as_slice(), &[4, 5]); + /// ``` #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_from<'a, I>( - this: &'a mut [MaybeUninit<T>], - it: I, - ) -> (&'a mut [T], &'a mut [MaybeUninit<T>]) + pub fn fill_from<I>(this: &mut [MaybeUninit<T>], it: I) -> (&mut [T], &mut [MaybeUninit<T>]) where I: IntoIterator<Item = T>, { @@ -1312,70 +1258,169 @@ impl<T> MaybeUninit<T> { // SAFETY: Valid elements have just been written into `init`, so that portion // of `this` is initialized. - (unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder) + (unsafe { initted.assume_init_mut() }, remainder) } - /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. + /// Deprecated version of [`slice::as_bytes`]. + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + #[deprecated( + note = "replaced by inherent as_bytes method; will eventually be removed", + since = "1.83.0" + )] + pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] { + this.as_bytes() + } + + /// Deprecated version of [`slice::as_bytes_mut`]. + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + #[deprecated( + note = "replaced by inherent as_bytes_mut method; will eventually be removed", + since = "1.83.0" + )] + pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] { + this.as_bytes_mut() + } +} + +impl<T> [MaybeUninit<T>] { + /// Copies the elements from `src` to `self`, + /// returning a mutable reference to the now initialized contents of `self`. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// If `T` does not implement `Copy`, use [`write_clone_of_slice`] instead. + /// + /// This is similar to [`slice::copy_from_slice`]. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. /// /// # Examples /// /// ``` - /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] + /// #![feature(maybe_uninit_write_slice)] /// use std::mem::MaybeUninit; /// - /// let val = 0x12345678_i32; - /// let uninit = MaybeUninit::new(val); - /// let uninit_bytes = uninit.as_bytes(); - /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) }; - /// assert_eq!(bytes, val.to_ne_bytes()); + /// let mut dst = [MaybeUninit::uninit(); 32]; + /// let src = [0; 32]; + /// + /// let init = dst.write_copy_of_slice(&src); + /// + /// assert_eq!(init, src); /// ``` - #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub fn as_bytes(&self) -> &[MaybeUninit<u8>] { - // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes - unsafe { - slice::from_raw_parts(self.as_ptr() as *const MaybeUninit<u8>, mem::size_of::<T>()) - } + /// + /// ``` + /// #![feature(maybe_uninit_write_slice)] + /// + /// let mut vec = Vec::with_capacity(32); + /// let src = [0; 16]; + /// + /// vec.spare_capacity_mut()[..src.len()].write_copy_of_slice(&src); + /// + /// // SAFETY: we have just copied all the elements of len into the spare capacity + /// // the first src.len() elements of the vec are valid now. + /// unsafe { + /// vec.set_len(src.len()); + /// } + /// + /// assert_eq!(vec, src); + /// ``` + /// + /// [`write_clone_of_slice`]: slice::write_clone_of_slice + #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + #[rustc_const_unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + pub const fn write_copy_of_slice(&mut self, src: &[T]) -> &mut [T] + where + T: Copy, + { + // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout + let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) }; + + self.copy_from_slice(uninit_src); + + // SAFETY: Valid elements have just been copied into `self` so it is initialized + unsafe { self.assume_init_mut() } } - /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized - /// bytes. + /// Clones the elements from `src` to `self`, + /// returning a mutable reference to the now initialized contents of `self`. + /// Any already initialized elements will not be dropped. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// If `T` implements `Copy`, use [`write_copy_of_slice`] instead. + /// + /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics. + /// + /// If there is a panic, the already cloned elements will be dropped. /// /// # Examples /// /// ``` - /// #![feature(maybe_uninit_as_bytes)] + /// #![feature(maybe_uninit_write_slice)] /// 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 mut dst = [const { MaybeUninit::uninit() }; 5]; + /// let src = ["wibbly", "wobbly", "timey", "wimey", "stuff"].map(|s| s.to_string()); + /// + /// let init = dst.write_clone_of_slice(&src); + /// + /// assert_eq!(init, src); + /// + /// # // Prevent leaks for Miri + /// # unsafe { std::ptr::drop_in_place(init); } + /// ``` + /// + /// ``` + /// #![feature(maybe_uninit_write_slice)] + /// + /// let mut vec = Vec::with_capacity(32); + /// let src = ["rust", "is", "a", "pretty", "cool", "language"].map(|s| s.to_string()); + /// + /// vec.spare_capacity_mut()[..src.len()].write_clone_of_slice(&src); + /// + /// // SAFETY: we have just cloned all the elements of len into the spare capacity + /// // the first src.len() elements of the vec are valid now. + /// unsafe { + /// vec.set_len(src.len()); /// } - /// let val2 = unsafe { uninit.assume_init() }; - /// assert_eq!(val2, 0x123456cd); + /// + /// assert_eq!(vec, src); /// ``` - #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] { - // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes - unsafe { - slice::from_raw_parts_mut( - self.as_mut_ptr() as *mut MaybeUninit<u8>, - mem::size_of::<T>(), - ) + /// + /// [`write_copy_of_slice`]: slice::write_copy_of_slice + #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + pub fn write_clone_of_slice(&mut self, src: &[T]) -> &mut [T] + where + T: Clone, + { + // unlike copy_from_slice this does not call clone_from_slice on the slice + // this is because `MaybeUninit<T: Clone>` does not implement Clone. + + assert_eq!(self.len(), src.len(), "destination and source slices have different lengths"); + + // NOTE: We need to explicitly slice them to the same length + // for bounds checking to be elided, and the optimizer will + // generate memcpy for simple cases (for example T = u8). + let len = self.len(); + let src = &src[..len]; + + // guard is needed b/c panic might happen during a clone + let mut guard = Guard { slice: self, initialized: 0 }; + + for i in 0..len { + guard.slice[i].write(src[i].clone()); + guard.initialized += 1; } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `self` so it is initialized + unsafe { self.assume_init_mut() } } - /// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized - /// bytes. + /// 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. @@ -1387,21 +1432,22 @@ impl<T> MaybeUninit<T> { /// use std::mem::MaybeUninit; /// /// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)]; - /// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit); - /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) }; + /// let uninit_bytes = uninit.as_bytes(); + /// let bytes = unsafe { uninit_bytes.assume_init_ref() }; /// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap()); /// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap()); /// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]); /// ``` #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] { - let bytes = mem::size_of_val(this); + pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] { // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes - unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit<u8>, bytes) } + unsafe { + slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of_val(self)) + } } - /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of - /// potentially uninitialized bytes. + /// Returns the contents of this `MaybeUninit` slice 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. @@ -1414,8 +1460,8 @@ impl<T> MaybeUninit<T> { /// /// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()]; /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit); - /// MaybeUninit::copy_from_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]); - /// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) }; + /// uninit_bytes.write_copy_of_slice(&[0x12, 0x34, 0x56, 0x78]); + /// let vals = unsafe { uninit.assume_init_ref() }; /// if cfg!(target_endian = "little") { /// assert_eq!(vals, &[0x3412u16, 0x7856u16]); /// } else { @@ -1423,10 +1469,74 @@ impl<T> MaybeUninit<T> { /// } /// ``` #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] { - let bytes = mem::size_of_val(this); + pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] { // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes - unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit<u8>, bytes) } + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr() as *mut MaybeUninit<u8>, + super::size_of_val(self), + ) + } + } + + /// Drops the contained values in place. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that every `MaybeUninit<T>` in the slice + /// really is in an initialized state. Calling this when the content is not yet + /// fully initialized causes undefined behavior. + /// + /// On top of that, all additional invariants of the type `T` must be + /// satisfied, as the `Drop` implementation of `T` (or its members) may + /// rely on this. For example, setting a `Vec<T>` to an invalid but + /// non-null address makes it 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. Dropping such a `Vec<T>` however will cause undefined + /// behaviour. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub unsafe fn assume_init_drop(&mut self) { + if !self.is_empty() { + // SAFETY: the caller must guarantee that every element of `self` + // is initialized and satisfies all invariants of `T`. + // Dropping the value in place is safe if that is the case. + unsafe { ptr::drop_in_place(self as *mut [MaybeUninit<T>] as *mut [T]) } + } + } + + /// Gets a shared reference to the contained value. + /// + /// # Safety + /// + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in + /// the slice really is in an initialized state. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const unsafe fn assume_init_ref(&self) -> &[T] { + // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that + // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. + // The pointer obtained is valid since it refers to memory owned by `slice` which is a + // reference and thus guaranteed to be valid for reads. + unsafe { &*(self as *const Self as *const [T]) } + } + + /// Gets a mutable (unique) reference to the contained value. + /// + /// # Safety + /// + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the + /// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot + /// be used to initialize a `MaybeUninit` slice. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const unsafe fn assume_init_mut(&mut self) -> &mut [T] { + // SAFETY: similar to safety notes for `slice_get_ref`, but we have a + // mutable reference which is also guaranteed to be valid for writes. + unsafe { &mut *(self as *mut Self as *mut [T]) } } } @@ -1479,7 +1589,7 @@ impl<'a, T> Drop for Guard<'a, T> { let initialized_part = &mut self.slice[..self.initialized]; // SAFETY: this raw sub-slice will contain only initialized objects. unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); + initialized_part.assume_init_drop(); } } } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 2d66e5c2f2a..b9bb6d6a13f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -333,7 +333,7 @@ pub const fn size_of<T>() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_size_of_val", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_size_of_val", since = "1.85.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] pub const fn size_of_val<T: ?Sized>(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer @@ -484,7 +484,7 @@ pub const fn align_of<T>() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_align_of_val", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_align_of_val", since = "1.85.0")] #[allow(deprecated)] pub const fn align_of_val<T: ?Sized>(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer @@ -725,7 +725,7 @@ pub unsafe fn uninitialized<T>() -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_swap", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_swap", since = "1.85.0")] #[rustc_diagnostic_item = "mem_swap"] pub const fn swap<T>(x: &mut T, y: &mut T) { // SAFETY: `&mut` guarantees these are typed readable and writable diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 9cf587650d9..6a4f84c849c 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -84,9 +84,8 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; /// `usize` is stable, but not portable. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_trait"] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] #[rustc_coinductive] pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }> where diff --git a/library/core/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs index bab84a97308..a7d12217081 100644 --- a/library/core/src/net/display_buffer.rs +++ b/library/core/src/net/display_buffer.rs @@ -18,7 +18,7 @@ impl<const SIZE: usize> DisplayBuffer<SIZE> { // SAFETY: `buf` is only written to by the `fmt::Write::write_str` implementation // which writes a valid UTF-8 string to `buf` and correctly sets `len`. unsafe { - let s = MaybeUninit::slice_assume_init_ref(&self.buf[..self.len]); + let s = self.buf[..self.len].assume_init_ref(); str::from_utf8_unchecked(s) } } @@ -29,7 +29,7 @@ impl<const SIZE: usize> fmt::Write for DisplayBuffer<SIZE> { let bytes = s.as_bytes(); if let Some(buf) = self.buf.get_mut(self.len..(self.len + bytes.len())) { - MaybeUninit::copy_from_slice(buf, bytes); + buf.write_copy_of_slice(bytes); self.len += bytes.len(); Ok(()) } else { diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 4c0d95f95e5..2b6adef65e9 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -818,7 +818,7 @@ impl f32 { /// ``` #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn recip(self) -> f32 { 1.0 / self @@ -836,7 +836,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_degrees(self) -> f32 { // Use a constant for better precision. @@ -856,7 +856,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_radians(self) -> f32 { const RADS_PER_DEG: f32 = consts::PI / 180.0; @@ -878,7 +878,7 @@ impl f32 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn max(self, other: f32) -> f32 { intrinsics::maxnumf32(self, other) @@ -899,7 +899,7 @@ impl f32 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn min(self, other: f32) -> f32 { intrinsics::minnumf32(self, other) @@ -988,8 +988,8 @@ impl f32 { /// assert_eq!((-5.5f32).midpoint(8.0), 1.25); /// ``` #[inline] - #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint", since = "1.85.0")] + #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] pub const fn midpoint(self, other: f32) -> f32 { cfg_if! { // Allow faster implementation that have known good 64-bit float @@ -1396,7 +1396,7 @@ impl f32 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn clamp(mut self, min: f32, max: f32) -> f32 { const_assert!( @@ -1433,7 +1433,7 @@ impl f32 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn abs(self) -> f32 { // SAFETY: this is actually a safe intrinsic @@ -1458,7 +1458,7 @@ impl f32 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn signum(self) -> f32 { if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) } @@ -1493,7 +1493,7 @@ impl f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "copysign", since = "1.35.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] pub const fn copysign(self, sign: f32) -> f32 { // SAFETY: this is actually a safe intrinsic unsafe { intrinsics::copysignf32(self, sign) } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 77ca56df067..037b3afa6c4 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -835,7 +835,7 @@ impl f64 { /// ``` #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn recip(self) -> f64 { 1.0 / self @@ -853,7 +853,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_degrees(self) -> f64 { // The division here is correctly rounded with respect to the true @@ -874,7 +874,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_radians(self) -> f64 { const RADS_PER_DEG: f64 = consts::PI / 180.0; @@ -896,7 +896,7 @@ impl f64 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn max(self, other: f64) -> f64 { intrinsics::maxnumf64(self, other) @@ -917,7 +917,7 @@ impl f64 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn min(self, other: f64) -> f64 { intrinsics::minnumf64(self, other) @@ -1006,8 +1006,8 @@ impl f64 { /// assert_eq!((-5.5f64).midpoint(8.0), 1.25); /// ``` #[inline] - #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint", since = "1.85.0")] + #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] pub const fn midpoint(self, other: f64) -> f64 { const LO: f64 = f64::MIN_POSITIVE * 2.; const HI: f64 = f64::MAX / 2.; @@ -1396,7 +1396,7 @@ impl f64 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn clamp(mut self, min: f64, max: f64) -> f64 { const_assert!( @@ -1433,7 +1433,7 @@ impl f64 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn abs(self) -> f64 { // SAFETY: this is actually a safe intrinsic @@ -1458,7 +1458,7 @@ impl f64 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn signum(self) -> f64 { if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) } @@ -1492,7 +1492,7 @@ impl f64 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] - #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn copysign(self, sign: f64) -> f64 { // SAFETY: this is actually a safe intrinsic diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs index d6413fadc33..7601e3e2c58 100644 --- a/library/core/src/num/flt2dec/mod.rs +++ b/library/core/src/num/flt2dec/mod.rs @@ -210,10 +210,10 @@ fn digits_to_dec_str<'a>( if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp { parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp)); // SAFETY: we just initialized the elements `..4`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } + unsafe { parts[..4].assume_init_ref() } } else { // SAFETY: we just initialized the elements `..3`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) } + unsafe { parts[..3].assume_init_ref() } } } else { let exp = exp as usize; @@ -225,10 +225,10 @@ fn digits_to_dec_str<'a>( if frac_digits > buf.len() - exp { parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp))); // SAFETY: we just initialized the elements `..4`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } + unsafe { parts[..4].assume_init_ref() } } else { // SAFETY: we just initialized the elements `..3`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) } + unsafe { parts[..3].assume_init_ref() } } } else { // the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__]. @@ -238,10 +238,10 @@ fn digits_to_dec_str<'a>( parts[2] = MaybeUninit::new(Part::Copy(b".")); parts[3] = MaybeUninit::new(Part::Zero(frac_digits)); // SAFETY: we just initialized the elements `..4`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } + unsafe { parts[..4].assume_init_ref() } } else { // SAFETY: we just initialized the elements `..2`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) } + unsafe { parts[..2].assume_init_ref() } } } } @@ -292,7 +292,7 @@ fn digits_to_exp_str<'a>( parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16)); } // SAFETY: we just initialized the elements `..n + 2`. - unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) } + unsafe { parts[..n + 2].assume_init_ref() } } /// Sign formatting options. @@ -366,12 +366,12 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Zero => { if frac_digits > 0 { @@ -381,14 +381,14 @@ where Formatted { sign, // SAFETY: we just initialized the elements `..2`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + parts: unsafe { parts[..2].assume_init_ref() }, } } else { parts[0] = MaybeUninit::new(Part::Copy(b"0")); Formatted { sign, // SAFETY: we just initialized the elements `..1`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + parts: unsafe { parts[..1].assume_init_ref() }, } } } @@ -442,12 +442,12 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Zero => { parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 { @@ -456,7 +456,7 @@ where MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" })) }; // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Finite(ref decoded) => { let (buf, exp) = format_shortest(decoded, buf); @@ -533,12 +533,12 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Zero => { if ndigits > 1 { @@ -549,14 +549,14 @@ where Formatted { sign, // SAFETY: we just initialized the elements `..3`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }, + parts: unsafe { parts[..3].assume_init_ref() }, } } else { parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" })); Formatted { sign, // SAFETY: we just initialized the elements `..1`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + parts: unsafe { parts[..1].assume_init_ref() }, } } } @@ -607,12 +607,12 @@ where FullDecoded::Nan => { parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Infinite => { parts[0] = MaybeUninit::new(Part::Copy(b"inf")); // SAFETY: we just initialized the elements `..1`. - Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } } } FullDecoded::Zero => { if frac_digits > 0 { @@ -622,14 +622,14 @@ where Formatted { sign, // SAFETY: we just initialized the elements `..2`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + parts: unsafe { parts[..2].assume_init_ref() }, } } else { parts[0] = MaybeUninit::new(Part::Copy(b"0")); Formatted { sign, // SAFETY: we just initialized the elements `..1`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + parts: unsafe { parts[..1].assume_init_ref() }, } } } @@ -654,14 +654,14 @@ where Formatted { sign, // SAFETY: we just initialized the elements `..2`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + parts: unsafe { parts[..2].assume_init_ref() }, } } else { parts[0] = MaybeUninit::new(Part::Copy(b"0")); Formatted { sign, // SAFETY: we just initialized the elements `..1`. - parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + parts: unsafe { parts[..1].assume_init_ref() }, } } } else { diff --git a/library/core/src/num/flt2dec/strategy/dragon.rs b/library/core/src/num/flt2dec/strategy/dragon.rs index e801f07b3bc..dd73e4b4846 100644 --- a/library/core/src/num/flt2dec/strategy/dragon.rs +++ b/library/core/src/num/flt2dec/strategy/dragon.rs @@ -247,7 +247,7 @@ pub fn format_shortest<'a>( // it seems that this condition is very hard to satisfy (possibly impossible), // but we are just being safe and consistent here. // SAFETY: we initialized that memory above. - if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }) { + if let Some(c) = round_up(unsafe { buf[..i].assume_init_mut() }) { buf[i] = MaybeUninit::new(c); i += 1; k += 1; @@ -255,7 +255,7 @@ pub fn format_shortest<'a>( } // SAFETY: we initialized that memory above. - (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..i]) }, k) + (unsafe { buf[..i].assume_init_ref() }, k) } /// The exact and fixed mode implementation for Dragon. @@ -333,7 +333,7 @@ pub fn format_exact<'a>( *c = MaybeUninit::new(b'0'); } // SAFETY: we initialized that memory above. - return (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k); + return (unsafe { buf[..len].assume_init_ref() }, k); } let mut d = 0; @@ -372,7 +372,7 @@ pub fn format_exact<'a>( // if rounding up changes the length, the exponent should also change. // but we've been requested a fixed number of digits, so do not alter the buffer... // SAFETY: we initialized that memory above. - if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) { + if let Some(c) = round_up(unsafe { buf[..len].assume_init_mut() }) { // ...unless we've been requested the fixed precision instead. // we also need to check that, if the original buffer was empty, // the additional digit can only be added when `k == limit` (edge case). @@ -385,5 +385,5 @@ pub fn format_exact<'a>( } // SAFETY: we initialized that memory above. - (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k) + (unsafe { buf[..len].assume_init_ref() }, k) } diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs index bdf544a4133..2816de4c633 100644 --- a/library/core/src/num/flt2dec/strategy/grisu.rs +++ b/library/core/src/num/flt2dec/strategy/grisu.rs @@ -275,7 +275,7 @@ pub fn format_shortest_opt<'a>( let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent return round_and_weed( // SAFETY: we initialized that memory above. - unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }, + unsafe { buf[..i].assume_init_mut() }, exp, plus1rem, delta1, @@ -324,7 +324,7 @@ pub fn format_shortest_opt<'a>( let ten_kappa = 1 << e; // implicit divisor return round_and_weed( // SAFETY: we initialized that memory above. - unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }, + unsafe { buf[..i].assume_init_mut() }, exp, r, threshold, @@ -713,7 +713,7 @@ pub fn format_exact_opt<'a>( // `10^kappa` did not overflow after all, the second check is fine. if ten_kappa - remainder > remainder && ten_kappa - 2 * remainder >= 2 * ulp { // SAFETY: our caller initialized that memory. - return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp)); + return Some((unsafe { buf[..len].assume_init_ref() }, exp)); } // :<------- remainder ------>| : @@ -736,7 +736,7 @@ pub fn format_exact_opt<'a>( if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp { if let Some(c) = // SAFETY: our caller must have initialized that memory. - round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) + round_up(unsafe { buf[..len].assume_init_mut() }) { // only add an additional digit when we've been requested the fixed precision. // we also need to check that, if the original buffer was empty, @@ -748,7 +748,7 @@ pub fn format_exact_opt<'a>( } } // SAFETY: we and our caller initialized that memory. - return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp)); + return Some((unsafe { buf[..len].assume_init_ref() }, exp)); } // otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 1f5b8ce6c6e..6c1b568e231 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -51,6 +51,10 @@ mod overflow_panic; mod saturating; mod wrapping; +/// 100% perma-unstable +#[doc(hidden)] +pub mod niche_types; + #[stable(feature = "rust1", since = "1.0.0")] #[cfg(not(no_fp_fmt_parse))] pub use dec2flt::ParseFloatError; @@ -138,8 +142,8 @@ macro_rules! midpoint_impl { #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] /// ``` - #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint", since = "1.85.0")] + #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -192,8 +196,8 @@ macro_rules! midpoint_impl { #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] /// ``` - #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint", since = "1.85.0")] + #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs new file mode 100644 index 00000000000..096713c318f --- /dev/null +++ b/library/core/src/num/niche_types.rs @@ -0,0 +1,168 @@ +#![unstable( + feature = "temporary_niche_types", + issue = "none", + reason = "for core, alloc, and std internals until pattern types are further along" +)] + +use crate::cmp::Ordering; +use crate::fmt; +use crate::hash::{Hash, Hasher}; +use crate::marker::StructuralPartialEq; + +macro_rules! define_valid_range_type { + ($( + $(#[$m:meta])* + $vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal); + )+) => {$( + #[derive(Clone, Copy, Eq)] + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start($low)] + #[rustc_layout_scalar_valid_range_end($high)] + $(#[$m])* + $vis struct $name($int); + + const _: () = { + // With the `valid_range` attributes, it's always specified as unsigned + assert!(<$uint>::MIN == 0); + let ulow: $uint = $low; + let uhigh: $uint = $high; + assert!(ulow <= uhigh); + + assert!(size_of::<$int>() == size_of::<$uint>()); + }; + + impl $name { + /// Constructs an instance of this type from the underlying integer + /// primitive without checking whether its zero. + /// + /// # Safety + /// Immediate language UB if `val == 0`, as it violates the validity + /// invariant of this type. + #[inline] + pub const unsafe fn new_unchecked(val: $int) -> Self { + // SAFETY: Caller promised that `val` is non-zero. + unsafe { $name(val) } + } + + #[inline] + pub const fn as_inner(self) -> $int { + // SAFETY: This is a transparent wrapper, so unwrapping it is sound + // (Not using `.0` due to MCP#807.) + unsafe { crate::mem::transmute(self) } + } + } + + // This is required to allow matching a constant. We don't get it from a derive + // because the derived `PartialEq` would do a field projection, which is banned + // by <https://github.com/rust-lang/compiler-team/issues/807>. + impl StructuralPartialEq for $name {} + + impl PartialEq for $name { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.as_inner() == other.as_inner() + } + } + + impl Ord for $name { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&self.as_inner(), &other.as_inner()) + } + } + + impl PartialOrd for $name { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(Ord::cmp(self, other)) + } + } + + impl Hash for $name { + // Required method + fn hash<H: Hasher>(&self, state: &mut H) { + Hash::hash(&self.as_inner(), state); + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + <$int as fmt::Debug>::fmt(&self.as_inner(), f) + } + } + )+}; +} + +define_valid_range_type! { + pub struct Nanoseconds(u32 as u32 in 0..=999_999_999); +} + +impl Nanoseconds { + // SAFETY: 0 is within the valid range + pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) }; +} + +impl Default for Nanoseconds { + #[inline] + fn default() -> Self { + Self::ZERO + } +} + +define_valid_range_type! { + pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff); + pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff); + pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff); + pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff); + pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); + + pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff); + pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff); + pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff); + pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff); + pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); +} + +#[cfg(target_pointer_width = "16")] +define_valid_range_type! { + pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff); + pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff); + pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff); +} +#[cfg(target_pointer_width = "32")] +define_valid_range_type! { + pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff); + pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff); + pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff); +} +#[cfg(target_pointer_width = "64")] +define_valid_range_type! { + pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff); + pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff); + pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff); +} + +define_valid_range_type! { + pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe); + pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe); + + pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe); + pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe); +} + +pub trait NotAllOnesHelper { + type Type; +} +pub type NotAllOnes<T> = <T as NotAllOnesHelper>::Type; +impl NotAllOnesHelper for u32 { + type Type = U32NotAllOnes; +} +impl NotAllOnesHelper for i32 { + type Type = I32NotAllOnes; +} +impl NotAllOnesHelper for u64 { + type Type = U64NotAllOnes; +} +impl NotAllOnesHelper for i64 { + type Type = I64NotAllOnes; +} diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index a9294306b1b..dbce64420ac 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -37,41 +37,12 @@ pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed { macro_rules! impl_zeroable_primitive { ($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => { mod private { - use super::*; - #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", issue = "none" )] pub trait Sealed {} - - $( - // This inner type is never shown directly, so intentionally does not have Debug - #[expect(missing_debug_implementations)] - // Since this struct is non-generic and derives Copy, - // the derived Clone is `*self` and thus doesn't field-project. - #[derive(Clone, Copy)] - #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start(1)] - #[rustc_nonnull_optimization_guaranteed] - #[unstable( - feature = "nonzero_internals", - reason = "implementation detail which may disappear or be replaced at any time", - issue = "none" - )] - pub struct $NonZeroInner($primitive); - - // This is required to allow matching a constant. We don't get it from a derive - // because the derived `PartialEq` would do a field projection, which is banned - // by <https://github.com/rust-lang/compiler-team/issues/807>. - #[unstable( - feature = "nonzero_internals", - reason = "implementation detail which may disappear or be replaced at any time", - issue = "none" - )] - impl StructuralPartialEq for $NonZeroInner {} - )+ } $( @@ -88,7 +59,7 @@ macro_rules! impl_zeroable_primitive { issue = "none" )] unsafe impl ZeroablePrimitive for $primitive { - type NonZeroInner = private::$NonZeroInner; + type NonZeroInner = super::niche_types::$NonZeroInner; } )+ }; @@ -1543,8 +1514,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Some(()) /// # } /// ``` - #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint", since = "1.85.0")] + #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 565bccf5898..810b906b871 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -73,7 +73,7 @@ append_const_msg )] #[doc(alias = "+")] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] pub trait Add<Rhs = Self> { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -95,18 +95,6 @@ pub trait Add<Rhs = Self> { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(bootstrap)] - impl Add for $t { - type Output = $t; - - #[inline] - #[track_caller] - #[rustc_inherit_overflow_checks] - fn add(self, other: $t) -> $t { self + other } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(not(bootstrap))] impl const Add for $t { type Output = $t; diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index 0073afd4960..c90ae7babbd 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -4,8 +4,7 @@ use crate::marker::Tuple; /// An async-aware version of the [`Fn`](crate::ops::Fn) trait. /// /// All `async fn` and functions returning futures implement this trait. -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[stable(feature = "async_closure", since = "1.85.0")] #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] @@ -19,8 +18,7 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> { /// An async-aware version of the [`FnMut`](crate::ops::FnMut) trait. /// /// All `async fn` and functions returning futures implement this trait. -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[stable(feature = "async_closure", since = "1.85.0")] #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] @@ -41,8 +39,7 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> { /// An async-aware version of the [`FnOnce`](crate::ops::FnOnce) trait. /// /// All `async fn` and functions returning futures implement this trait. -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[stable(feature = "async_closure", since = "1.85.0")] #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] @@ -67,8 +64,7 @@ mod impls { use super::{AsyncFn, AsyncFnMut, AsyncFnOnce}; use crate::marker::Tuple; - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<A: Tuple, F: ?Sized> AsyncFn<A> for &F where F: AsyncFn<A>, @@ -78,8 +74,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &F where F: AsyncFn<A>, @@ -94,8 +89,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a F where F: AsyncFn<A>, @@ -108,8 +102,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &mut F where F: AsyncFnMut<A>, @@ -124,8 +117,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a mut F where F: AsyncFnMut<A>, diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index c36d55fe2a8..ed0d30a0f50 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -133,7 +133,7 @@ #[doc(alias = "&*")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] @@ -148,18 +148,6 @@ pub trait Deref { fn deref(&self) -> &Self::Target; } -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> Deref for &T { - type Target = T; - - #[rustc_diagnostic_item = "noop_method_deref"] - fn deref(&self) -> &T { - *self - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> const Deref for &T { type Target = T; @@ -173,17 +161,6 @@ impl<T: ?Sized> const Deref for &T { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> !DerefMut for &T {} -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> Deref for &mut T { - type Target = T; - - fn deref(&self) -> &T { - *self - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> const Deref for &mut T { type Target = T; @@ -282,7 +259,6 @@ impl<T: ?Sized> const Deref for &mut T { /// *x = 'b'; /// assert_eq!('b', x.value); /// ``` -#[cfg(not(bootstrap))] #[lang = "deref_mut"] #[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] @@ -294,27 +270,6 @@ pub trait DerefMut: ~const Deref { fn deref_mut(&mut self) -> &mut Self::Target; } -/// Bootstrap -#[lang = "deref_mut"] -#[doc(alias = "*")] -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(bootstrap)] -pub trait DerefMut: Deref { - /// Mutably dereferences the value. - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_diagnostic_item = "deref_mut_method"] - fn deref_mut(&mut self) -> &mut Self::Target; -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> DerefMut for &mut T { - fn deref_mut(&mut self) -> &mut T { - *self - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> const DerefMut for &mut T { fn deref_mut(&mut self) -> &mut T { diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index f3314364e54..78b5252195f 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -203,7 +203,7 @@ /// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] pub trait Drop { /// Executes the destructor for this type. /// diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index 9b23874bcf7..d3fda1cd273 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -71,7 +71,7 @@ pub mod rust_2021 { /// The 2024 version of the core prelude. /// /// See the [module-level documentation](self) for more. -#[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "prelude_2024", since = "1.85.0")] pub mod rust_2024 { #[stable(feature = "rust1", since = "1.0.0")] pub use super::common::*; @@ -84,7 +84,7 @@ pub mod rust_2024 { #[doc(no_inline)] pub use crate::convert::{TryFrom, TryInto}; - #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "prelude_2024", since = "1.85.0")] #[doc(no_inline)] pub use crate::future::{Future, IntoFuture}; } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index b1d5e1fa3a0..e93b5658e24 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -53,9 +53,8 @@ use crate::ptr::NonNull; /// /// [`to_raw_parts`]: *const::to_raw_parts #[lang = "pointee_trait"] -#[cfg_attr(bootstrap, rustc_deny_explicit_impl(implement_via_object = false))] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] -#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] +#[rustc_deny_explicit_impl] +#[rustc_do_not_implement_via_object] pub trait Pointee { /// The type for metadata in pointers and references to `Self`. #[lang = "metadata_type"] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index a70af793004..f58c0e12411 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -777,7 +777,7 @@ pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T { /// # type T = i32; /// # fn foo() -> T { 42 } /// // The temporary holding the return value of `foo` does *not* have its lifetime extended, -/// // because the surrounding expression involves no function call. +/// // because the surrounding expression involves a function call. /// let p = ptr::from_ref(&foo()); /// unsafe { p.read() }; // UB! Reading from a dangling pointer ⚠️ /// ``` @@ -828,7 +828,7 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T { /// # type T = i32; /// # fn foo() -> T { 42 } /// // The temporary holding the return value of `foo` does *not* have its lifetime extended, -/// // because the surrounding expression involves no function call. +/// // because the surrounding expression involves a function call. /// let p = ptr::from_mut(&mut foo()); /// unsafe { p.write(T::default()) }; // UB! Writing to a dangling pointer ⚠️ /// ``` @@ -1009,7 +1009,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_swap", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_swap", since = "1.85.0")] #[rustc_diagnostic_item = "ptr_swap"] pub const unsafe fn swap<T>(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. @@ -2150,7 +2150,7 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { /// ``` /// /// [subtype]: https://doc.rust-lang.org/reference/subtyping.html -#[stable(feature = "ptr_fn_addr_eq", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ptr_fn_addr_eq", since = "1.85.0")] #[inline(always)] #[must_use = "function pointer comparison produces a value"] pub fn fn_addr_eq<T: FnPtr, U: FnPtr>(f: T, g: U) -> bool { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d75d570a969..5d9d337f101 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1594,7 +1594,7 @@ impl<T: ?Sized> *mut T { /// /// [`ptr::swap`]: crate::ptr::swap() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_swap", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_swap", since = "1.85.0")] #[inline(always)] pub const unsafe fn swap(self, with: *mut T) where diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 1058fa42cc1..2c9131254f7 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -85,6 +85,20 @@ impl<T: ?Sized> !Send for NonNull<T> {} impl<T: ?Sized> !Sync for NonNull<T> {} impl<T: Sized> NonNull<T> { + /// 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`]. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[unstable(feature = "nonnull_provenance", issue = "135243")] + pub const fn without_provenance(addr: NonZero<usize>) -> Self { + // SAFETY: we know `addr` is non-zero. + unsafe { + let ptr = crate::ptr::without_provenance_mut(addr.get()); + NonNull::new_unchecked(ptr) + } + } + /// Creates a new `NonNull` that is dangling, but well-aligned. /// /// This is useful for initializing types which lazily allocate, like @@ -116,6 +130,21 @@ impl<T: Sized> NonNull<T> { } } + /// Converts an address back to a mutable pointer, picking up some previously 'exposed' + /// [provenance][crate::ptr#provenance]. + /// + /// For more details, see the equivalent method on a raw pointer, [`ptr::with_exposed_provenance_mut`]. + /// + /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. + #[unstable(feature = "nonnull_provenance", issue = "135243")] + pub fn with_exposed_provenance(addr: NonZero<usize>) -> Self { + // SAFETY: we know `addr` is non-zero. + unsafe { + let ptr = crate::ptr::with_exposed_provenance_mut(addr.get()); + NonNull::new_unchecked(ptr) + } + } + /// Returns a shared references to the value. In contrast to [`as_ref`], this does not require /// that the value has to be initialized. /// @@ -224,7 +253,7 @@ impl<T: ?Sized> NonNull<T> { /// } /// ``` #[stable(feature = "nonnull", since = "1.25.0")] - #[rustc_const_stable(feature = "const_nonnull_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_nonnull_new", since = "1.85.0")] #[inline] pub const fn new(ptr: *mut T) -> Option<Self> { if !ptr.is_null() { @@ -282,7 +311,7 @@ impl<T: ?Sized> NonNull<T> { /// Gets the "address" portion of the pointer. /// - /// For more details see the equivalent method on a raw pointer, [`pointer::addr`]. + /// For more details, see the equivalent method on a raw pointer, [`pointer::addr`]. /// /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] @@ -294,10 +323,23 @@ impl<T: ?Sized> NonNull<T> { unsafe { NonZero::new_unchecked(self.as_ptr().addr()) } } + /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in + /// [`with_exposed_provenance`][NonNull::with_exposed_provenance] and returns the "address" portion. + /// + /// For more details, see the equivalent method on a raw pointer, [`pointer::expose_provenance`]. + /// + /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. + #[unstable(feature = "nonnull_provenance", issue = "135243")] + pub fn expose_provenance(self) -> NonZero<usize> { + // SAFETY: The pointer is guaranteed by the type to be non-null, + // meaning that the address will be non-zero. + unsafe { NonZero::new_unchecked(self.as_ptr().expose_provenance()) } + } + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of /// `self`. /// - /// For more details see the equivalent method on a raw pointer, [`pointer::with_addr`]. + /// For more details, see the equivalent method on a raw pointer, [`pointer::with_addr`]. /// /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] @@ -311,7 +353,7 @@ impl<T: ?Sized> NonNull<T> { /// Creates a new pointer by mapping `self`'s address to a new one, preserving the /// [provenance][crate::ptr#provenance] of `self`. /// - /// For more details see the equivalent method on a raw pointer, [`pointer::map_addr`]. + /// For more details, see the equivalent method on a raw pointer, [`pointer::map_addr`]. /// /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] @@ -1146,7 +1188,7 @@ impl<T: ?Sized> NonNull<T> { /// [`ptr::swap`]: crate::ptr::swap() #[inline(always)] #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_swap", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_swap", since = "1.85.0")] pub const unsafe fn swap(self, with: NonNull<T>) where T: Sized, @@ -1556,7 +1598,6 @@ impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: U unsafe impl<T: ?Sized> PinCoerceUnsized for NonNull<T> {} #[unstable(feature = "pointer_like_trait", issue = "none")] -#[cfg(not(bootstrap))] impl<T> core::marker::PointerLike for NonNull<T> {} #[stable(feature = "nonnull", since = "1.25.0")] diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index d2842f69008..a687ed7129d 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -49,7 +49,7 @@ impl<'a, T> IntoIterator for &'a mut [T] { /// // First, we need a slice to call the `iter` method on: /// let slice = &[1, 2, 3]; /// -/// // Then we call `iter` on the slice to get the `Iter` struct, +/// // Then we call `iter` on the slice to get the `Iter` iterator, /// // and iterate over it: /// for element in slice.iter() { /// println!("{element}"); @@ -107,24 +107,20 @@ impl<'a, T> Iter<'a, T> { /// Views the underlying data as a subslice of the original data. /// - /// This has the same lifetime as the original slice, and so the - /// iterator can continue to be used while this exists. - /// /// # Examples /// /// Basic usage: /// /// ``` /// // First, we need a slice to call the `iter` method on: - /// // struct (`&[usize]` here): /// let slice = &[1, 2, 3]; /// - /// // Then we call `iter` on the slice to get the `Iter` struct: + /// // Then we call `iter` on the slice to get the `Iter` iterator: /// let mut iter = slice.iter(); /// // Here `as_slice` still returns the whole slice, so this prints "[1, 2, 3]": /// println!("{:?}", iter.as_slice()); /// - /// // Now, we call the `next` method to remove the first element of the iterator: + /// // Now, we call the `next` method to remove the first element from the iterator: /// iter.next(); /// // Here the iterator does not contain the first element of the slice any more, /// // so `as_slice` only returns the last two elements of the slice, @@ -181,7 +177,7 @@ impl<T> AsRef<[T]> for Iter<'_, T> { /// // First, we need a slice to call the `iter_mut` method on: /// let slice = &mut [1, 2, 3]; /// -/// // Then we call `iter_mut` on the slice to get the `IterMut` struct, +/// // Then we call `iter_mut` on the slice to get the `IterMut` iterator, /// // iterate over it and increment each element value: /// for element in slice.iter_mut() { /// *element += 1; @@ -286,25 +282,30 @@ impl<'a, T> IterMut<'a, T> { /// Views the underlying data as a subslice of the original data. /// - /// To avoid creating `&mut [T]` references that alias, the returned slice - /// borrows its lifetime from the iterator the method is applied on. - /// /// # Examples /// /// Basic usage: /// /// ``` - /// let mut slice: &mut [usize] = &mut [1, 2, 3]; + /// // First, we need a slice to call the `iter_mut` method on: + /// let slice = &mut [1, 2, 3]; /// - /// // First, we get the iterator: + /// // Then we call `iter_mut` on the slice to get the `IterMut` iterator: /// let mut iter = slice.iter_mut(); - /// // So if we check what the `as_slice` method returns here, we have "[1, 2, 3]": - /// assert_eq!(iter.as_slice(), &[1, 2, 3]); + /// // Here `as_slice` still returns the whole slice, so this prints "[1, 2, 3]": + /// println!("{:?}", iter.as_slice()); /// - /// // Next, we move to the second element of the slice: - /// iter.next(); - /// // Now `as_slice` returns "[2, 3]": - /// assert_eq!(iter.as_slice(), &[2, 3]); + /// // Now, we call the `next` method to remove the first element from the iterator + /// // and increment its value: + /// *iter.next().unwrap() += 1; + /// // Here the iterator does not contain the first element of the slice any more, + /// // so `as_slice` only returns the last two elements of the slice, + /// // and so this prints "[2, 3]": + /// println!("{:?}", iter.as_slice()); + /// + /// // The underlying slice still contains three elements, but its first element + /// // was increased by 1, so this prints "[2, 2, 3]": + /// println!("{:?}", slice); /// ``` #[must_use] #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] @@ -315,9 +316,6 @@ impl<'a, T> IterMut<'a, T> { /// Views the underlying data as a mutable subslice of the original data. /// - /// To avoid creating `&mut [T]` references that alias, the returned slice - /// borrows its lifetime from the iterator the method is applied on. - /// /// # Examples /// /// Basic usage: diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 073cca7daef..5a22110880c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -913,7 +913,7 @@ impl<T> [T] { /// assert!(v == ["a", "b", "e", "d", "c"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_swap", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_swap", since = "1.85.0")] #[inline] #[track_caller] pub const fn swap(&mut self, a: usize, b: usize) { @@ -987,8 +987,9 @@ impl<T> [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_reverse", issue = "135120")] #[inline] - pub fn reverse(&mut self) { + pub const fn reverse(&mut self) { let half_len = self.len() / 2; let Range { start, end } = self.as_mut_ptr_range(); @@ -1011,7 +1012,7 @@ impl<T> [T] { revswap(front_half, back_half, half_len); #[inline] - fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) { + const fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) { debug_assert!(a.len() == n); debug_assert!(b.len() == n); @@ -1019,7 +1020,8 @@ impl<T> [T] { // this check tells LLVM that the indexing below is // in-bounds. Then after inlining -- once the actual // lengths of the slices are known -- it's removed. - let (a, b) = (&mut a[..n], &mut b[..n]); + let (a, _) = a.split_at_mut(n); + let (b, _) = b.split_at_mut(n); let mut i = 0; while i < n { @@ -3701,6 +3703,7 @@ impl<T> [T] { /// [`clone_from_slice`]: slice::clone_from_slice /// [`split_at_mut`]: slice::split_at_mut #[doc(alias = "memcpy")] + #[inline] #[stable(feature = "copy_from_slice", since = "1.9.0")] #[rustc_const_unstable(feature = "const_copy_from_slice", issue = "131415")] #[track_caller] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index ba429005fab..4c51ca0a5e4 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -60,7 +60,7 @@ impl RawWaker { RawWaker { data, vtable } } - #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "noop_waker", since = "1.85.0")] const NOOP: RawWaker = { const VTABLE: RawWakerVTable = RawWakerVTable::new( // Cloning just returns a new no-op raw waker @@ -564,8 +564,8 @@ impl Waker { /// ``` #[inline] #[must_use] - #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "noop_waker", since = "1.85.0")] + #[rustc_const_stable(feature = "noop_waker", since = "1.85.0")] pub const fn noop() -> &'static Waker { const WAKER: &Waker = &Waker { waker: RawWaker::NOOP }; WAKER diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 2d93148bac0..22bd46c567e 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -21,6 +21,7 @@ use crate::fmt; use crate::iter::Sum; +use crate::num::niche_types::Nanoseconds; use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; const NANOS_PER_SEC: u32 = 1_000_000_000; @@ -37,24 +38,6 @@ const HOURS_PER_DAY: u64 = 24; #[unstable(feature = "duration_units", issue = "120301")] const DAYS_PER_WEEK: u64 = 7; -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -#[rustc_layout_scalar_valid_range_end(999_999_999)] -struct Nanoseconds(u32); - -impl Nanoseconds { - // SAFETY: 0 is within the valid range - const ZERO: Self = unsafe { Nanoseconds(0) }; -} - -impl Default for Nanoseconds { - #[inline] - fn default() -> Self { - Self::ZERO - } -} - /// A `Duration` type to represent a span of time, typically used for system /// timeouts. /// @@ -211,14 +194,14 @@ impl Duration { pub const fn new(secs: u64, nanos: u32) -> Duration { if nanos < NANOS_PER_SEC { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range - Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + Duration { secs, nanos: unsafe { Nanoseconds::new_unchecked(nanos) } } } else { let secs = secs .checked_add((nanos / NANOS_PER_SEC) as u64) .expect("overflow in Duration::new"); let nanos = nanos % NANOS_PER_SEC; // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range - Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + Duration { secs, nanos: unsafe { Nanoseconds::new_unchecked(nanos) } } } } @@ -263,7 +246,7 @@ impl Duration { let subsec_millis = (millis % MILLIS_PER_SEC) as u32; // SAFETY: (x % 1_000) * 1_000_000 < 1_000_000_000 // => x % 1_000 < 1_000 - let subsec_nanos = unsafe { Nanoseconds(subsec_millis * NANOS_PER_MILLI) }; + let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_millis * NANOS_PER_MILLI) }; Duration { secs, nanos: subsec_nanos } } @@ -289,7 +272,7 @@ impl Duration { let subsec_micros = (micros % MICROS_PER_SEC) as u32; // SAFETY: (x % 1_000_000) * 1_000 < 1_000_000_000 // => x % 1_000_000 < 1_000_000 - let subsec_nanos = unsafe { Nanoseconds(subsec_micros * NANOS_PER_MICRO) }; + let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_micros * NANOS_PER_MICRO) }; Duration { secs, nanos: subsec_nanos } } @@ -320,7 +303,7 @@ impl Duration { let secs = nanos / NANOS_PER_SEC; let subsec_nanos = (nanos % NANOS_PER_SEC) as u32; // SAFETY: x % 1_000_000_000 < 1_000_000_000 - let subsec_nanos = unsafe { Nanoseconds(subsec_nanos) }; + let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_nanos) }; Duration { secs, nanos: subsec_nanos } } @@ -458,7 +441,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] #[inline] pub const fn is_zero(&self) -> bool { - self.secs == 0 && self.nanos.0 == 0 + self.secs == 0 && self.nanos.as_inner() == 0 } /// Returns the number of _whole_ seconds contained by this `Duration`. @@ -509,7 +492,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_millis(&self) -> u32 { - self.nanos.0 / NANOS_PER_MILLI + self.nanos.as_inner() / NANOS_PER_MILLI } /// Returns the fractional part of this `Duration`, in whole microseconds. @@ -532,7 +515,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_micros(&self) -> u32 { - self.nanos.0 / NANOS_PER_MICRO + self.nanos.as_inner() / NANOS_PER_MICRO } /// Returns the fractional part of this `Duration`, in nanoseconds. @@ -555,7 +538,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_nanos(&self) -> u32 { - self.nanos.0 + self.nanos.as_inner() } /// Returns the total number of whole milliseconds contained by this `Duration`. @@ -573,7 +556,8 @@ impl Duration { #[must_use] #[inline] pub const fn as_millis(&self) -> u128 { - self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128 + self.secs as u128 * MILLIS_PER_SEC as u128 + + (self.nanos.as_inner() / NANOS_PER_MILLI) as u128 } /// Returns the total number of whole microseconds contained by this `Duration`. @@ -591,7 +575,8 @@ impl Duration { #[must_use] #[inline] pub const fn as_micros(&self) -> u128 { - self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128 + self.secs as u128 * MICROS_PER_SEC as u128 + + (self.nanos.as_inner() / NANOS_PER_MICRO) as u128 } /// Returns the total number of nanoseconds contained by this `Duration`. @@ -609,7 +594,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_nanos(&self) -> u128 { - self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128 + self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.as_inner() as u128 } /// Computes the absolute difference between `self` and `other`. @@ -649,7 +634,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_add(self, rhs: Duration) -> Option<Duration> { if let Some(mut secs) = self.secs.checked_add(rhs.secs) { - let mut nanos = self.nanos.0 + rhs.nanos.0; + let mut nanos = self.nanos.as_inner() + rhs.nanos.as_inner(); if nanos >= NANOS_PER_SEC { nanos -= NANOS_PER_SEC; if let Some(new_secs) = secs.checked_add(1) { @@ -707,11 +692,11 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { - let nanos = if self.nanos.0 >= rhs.nanos.0 { - self.nanos.0 - rhs.nanos.0 + let nanos = if self.nanos.as_inner() >= rhs.nanos.as_inner() { + self.nanos.as_inner() - rhs.nanos.as_inner() } else if let Some(sub_secs) = secs.checked_sub(1) { secs = sub_secs; - self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0 + self.nanos.as_inner() + NANOS_PER_SEC - rhs.nanos.as_inner() } else { return None; }; @@ -763,7 +748,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_mul(self, rhs: u32) -> Option<Duration> { // Multiply nanoseconds as u64, because it cannot overflow that way. - let total_nanos = self.nanos.0 as u64 * rhs as u64; + let total_nanos = self.nanos.as_inner() as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; // FIXME(const-hack): use `and_then` once that is possible. @@ -820,7 +805,8 @@ impl Duration { pub const fn checked_div(self, rhs: u32) -> Option<Duration> { if rhs != 0 { let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64)); - let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs); + let (mut nanos, extra_nanos) = + (self.nanos.as_inner() / rhs, self.nanos.as_inner() % rhs); nanos += ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32; debug_assert!(nanos < NANOS_PER_SEC); @@ -846,7 +832,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f64(&self) -> f64 { - (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) + (self.secs as f64) + (self.nanos.as_inner() as f64) / (NANOS_PER_SEC as f64) } /// Returns the number of seconds contained by this `Duration` as `f32`. @@ -865,7 +851,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f32(&self) -> f32 { - (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) + (self.secs as f32) + (self.nanos.as_inner() as f32) / (NANOS_PER_SEC as f32) } /// Returns the number of milliseconds contained by this `Duration` as `f64`. @@ -885,7 +871,7 @@ impl Duration { #[inline] pub const fn as_millis_f64(&self) -> f64 { (self.secs as f64) * (MILLIS_PER_SEC as f64) - + (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64) + + (self.nanos.as_inner() as f64) / (NANOS_PER_MILLI as f64) } /// Returns the number of milliseconds contained by this `Duration` as `f32`. @@ -905,7 +891,7 @@ impl Duration { #[inline] pub const fn as_millis_f32(&self) -> f32 { (self.secs as f32) * (MILLIS_PER_SEC as f32) - + (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32) + + (self.nanos.as_inner() as f32) / (NANOS_PER_MILLI as f32) } /// Creates a new `Duration` from the specified number of seconds represented @@ -1084,8 +1070,9 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { - let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); - let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); + let self_nanos = + (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.as_inner() as f64); + let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.as_inner() as f64); self_nanos / rhs_nanos } @@ -1105,8 +1092,9 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { - let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); - let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); + let self_nanos = + (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.as_inner() as f32); + let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.as_inner() as f32); self_nanos / rhs_nanos } } @@ -1201,13 +1189,13 @@ macro_rules! sum_durations { for entry in $iter { total_secs = total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); - total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) { + total_nanos = match total_nanos.checked_add(entry.nanos.as_inner() as u64) { Some(n) => n, None => { total_secs = total_secs .checked_add(total_nanos / NANOS_PER_SEC as u64) .expect("overflow in iter::sum over durations"); - (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64 + (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.as_inner() as u64 } }; } @@ -1399,27 +1387,27 @@ impl fmt::Debug for Duration { let prefix = if f.sign_plus() { "+" } else { "" }; if self.secs > 0 { - fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s") - } else if self.nanos.0 >= NANOS_PER_MILLI { + fmt_decimal(f, self.secs, self.nanos.as_inner(), NANOS_PER_SEC / 10, prefix, "s") + } else if self.nanos.as_inner() >= NANOS_PER_MILLI { fmt_decimal( f, - (self.nanos.0 / NANOS_PER_MILLI) as u64, - self.nanos.0 % NANOS_PER_MILLI, + (self.nanos.as_inner() / NANOS_PER_MILLI) as u64, + self.nanos.as_inner() % NANOS_PER_MILLI, NANOS_PER_MILLI / 10, prefix, "ms", ) - } else if self.nanos.0 >= NANOS_PER_MICRO { + } else if self.nanos.as_inner() >= NANOS_PER_MICRO { fmt_decimal( f, - (self.nanos.0 / NANOS_PER_MICRO) as u64, - self.nanos.0 % NANOS_PER_MICRO, + (self.nanos.as_inner() / NANOS_PER_MICRO) as u64, + self.nanos.as_inner() % NANOS_PER_MICRO, NANOS_PER_MICRO / 10, prefix, "µs", ) } else { - fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns") + fmt_decimal(f, self.nanos.as_inner() as u64, 0, 1, prefix, "ns") } } } |
