From 7218fd19e035b54918336b6cd027e6b407ffa540 Mon Sep 17 00:00:00 2001 From: tison Date: Sun, 22 Dec 2024 19:48:33 +0800 Subject: Impl String::into_chars Signed-off-by: tison --- library/alloc/src/string.rs | 187 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 23d060d2158..0c9535dfaa6 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -62,10 +62,10 @@ use crate::alloc::Allocator; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::collections::TryReserveError; -use crate::str::{self, Chars, Utf8Error, from_utf8_unchecked_mut}; +use crate::str::{self, CharIndices, Chars, Utf8Error, from_utf8_unchecked_mut}; #[cfg(not(no_global_oom_handling))] use crate::str::{FromStr, from_boxed_utf8_unchecked}; -use crate::vec::Vec; +use crate::vec::{self, Vec}; /// A UTF-8–encoded, growable string. /// @@ -1952,6 +1952,61 @@ impl String { Drain { start, end, iter: chars_iter, string: self_ptr } } + /// Converts a `String` into an iterator over the [`char`]s of the string. + /// + /// As a string consists of valid UTF-8, we can iterate through a string + /// by [`char`]. This method returns such an iterator. + /// + /// It's important to remember that [`char`] represents a Unicode Scalar + /// Value, and might not match your idea of what a 'character' is. Iteration + /// over grapheme clusters may be what you actually want. That functionality + /// is not provided by Rust's standard library, check crates.io instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let word = String::from("goodbye"); + /// + /// let mut chars = word.into_chars(); + /// + /// assert_eq!(Some('g'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('d'), chars.next()); + /// assert_eq!(Some('b'), chars.next()); + /// assert_eq!(Some('y'), chars.next()); + /// assert_eq!(Some('e'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// Remember, [`char`]s might not match your intuition about characters: + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let y = String::from("y̆"); + /// + /// let mut chars = y.into_chars(); + /// + /// assert_eq!(Some('y'), chars.next()); // not 'y̆' + /// assert_eq!(Some('\u{0306}'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// [`char`]: prim@char + #[inline] + #[must_use = "`self` will be dropped if the result is not used"] + #[unstable(feature = "string_into_chars", issue = "133125")] + pub fn into_chars(self) -> IntoChars { + IntoChars { bytes: self.into_bytes().into_iter() } + } + /// Removes the specified range in the string, /// and replaces it with the given string. /// The given string doesn't need to be the same length as the range. @@ -3090,6 +3145,134 @@ impl fmt::Write for String { } } +/// An iterator over the [`char`]s of a string. +/// +/// This struct is created by the [`into_chars`] method on [`String`]. +/// See its documentation for more. +/// +/// [`char`]: prim@char +/// [`into_chars`]: String::into_chars +#[cfg_attr(not(no_global_oom_handling), derive(Clone))] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "string_into_chars", issue = "133125")] +pub struct IntoChars { + bytes: vec::IntoIter, +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl fmt::Debug for IntoChars { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoChars").field(&self.as_str()).finish() + } +} + +impl IntoChars { + /// Views the underlying data as a subslice of the original data. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let mut chars = String::from("abc").into_chars(); + /// + /// assert_eq!(chars.as_str(), "abc"); + /// chars.next(); + /// assert_eq!(chars.as_str(), "bc"); + /// chars.next(); + /// chars.next(); + /// assert_eq!(chars.as_str(), ""); + /// ``` + #[unstable(feature = "string_into_chars", issue = "133125")] + #[must_use] + #[inline] + pub fn as_str(&self) -> &str { + // SAFETY: `bytes` is a valid UTF-8 string. + unsafe { str::from_utf8_unchecked(self.bytes.as_slice()) } + } + + /// Consumes the `IntoChars`, returning the remaining string. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_into_chars)] + /// + /// let chars = String::from("abc").into_chars(); + /// assert_eq!(chars.into_string(), "abc"); + /// + /// let mut chars = String::from("def").into_chars(); + /// chars.next(); + /// assert_eq!(chars.into_string(), "ef"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_into_chars", issue = "133125")] + #[inline] + pub fn into_string(self) -> String { + // Safety: `bytes` are kept in UTF-8 form, only removing whole `char`s at a time. + unsafe { String::from_utf8_unchecked(self.bytes.collect()) } + } + + #[inline] + fn iter(&self) -> CharIndices<'_> { + self.as_str().char_indices() + } +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl Iterator for IntoChars { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + let mut iter = self.iter(); + match iter.next() { + None => None, + Some((_, ch)) => { + let offset = iter.offset(); + // `offset` is a valid index. + let _ = self.bytes.advance_by(offset); + Some(ch) + } + } + } + + #[inline] + fn count(self) -> usize { + self.iter().count() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter().size_hint() + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl DoubleEndedIterator for IntoChars { + #[inline] + fn next_back(&mut self) -> Option { + let len = self.as_str().len(); + let mut iter = self.iter(); + match iter.next_back() { + None => None, + Some((idx, ch)) => { + // `idx` is a valid index. + let _ = self.bytes.advance_back_by(len - idx); + Some(ch) + } + } + } +} + +#[unstable(feature = "string_into_chars", issue = "133125")] +impl FusedIterator for IntoChars {} + /// A draining iterator for `String`. /// /// This struct is created by the [`drain`] method on [`String`]. See its -- cgit 1.4.1-3-g733a5 From 4ae92b7adbafd018bf0c829a4691ffbb3933d8f0 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 6 Jan 2025 20:28:08 +0100 Subject: update version placeholders --- compiler/rustc_feature/src/accepted.rs | 6 +++--- compiler/rustc_feature/src/removed.rs | 2 +- compiler/rustc_feature/src/unstable.rs | 22 +++++++++++----------- library/alloc/src/boxed.rs | 6 +++--- library/core/src/alloc/layout.rs | 10 +++++----- library/core/src/hash/mod.rs | 4 ++-- library/core/src/iter/traits/collect.rs | 2 +- library/core/src/mem/maybe_uninit.rs | 2 +- library/core/src/mem/mod.rs | 6 +++--- library/core/src/num/f32.rs | 22 +++++++++++----------- library/core/src/num/f64.rs | 22 +++++++++++----------- library/core/src/num/mod.rs | 8 ++++---- library/core/src/num/nonzero.rs | 4 ++-- library/core/src/ops/async_function.rs | 16 ++++++++-------- library/core/src/prelude/mod.rs | 4 ++-- library/core/src/ptr/mod.rs | 4 ++-- library/core/src/ptr/mut_ptr.rs | 2 +- library/core/src/ptr/non_null.rs | 4 ++-- library/core/src/slice/mod.rs | 2 +- library/core/src/task/wake.rs | 6 +++--- library/std/src/collections/hash/map.rs | 2 +- library/std/src/collections/hash/set.rs | 2 +- library/std/src/env.rs | 2 +- library/std/src/io/error.rs | 4 ++-- library/std/src/prelude/common.rs | 2 +- library/std/src/prelude/mod.rs | 4 ++-- src/doc/rustc/src/check-cfg.md | 2 +- 27 files changed, 86 insertions(+), 86 deletions(-) (limited to 'library/alloc/src') diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 776de1988cc..217a7aeb2d7 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -73,7 +73,7 @@ declare_features! ( /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. (accepted, async_await, "1.39.0", Some(50547)), /// Allows `async || body` closures. - (accepted, async_closure, "CURRENT_RUSTC_VERSION", Some(62290)), + (accepted, async_closure, "1.85.0", Some(62290)), /// Allows async functions to be declared, implemented, and used in traits. (accepted, async_fn_in_trait, "1.75.0", Some(91611)), /// Allows all literals in attribute lists and values of key-value pairs. @@ -176,7 +176,7 @@ declare_features! ( /// Allows using the `#[diagnostic]` attribute tool namespace (accepted, diagnostic_namespace, "1.78.0", Some(111996)), /// Controls errors in trait implementations. - (accepted, do_not_recommend, "CURRENT_RUSTC_VERSION", Some(51992)), + (accepted, do_not_recommend, "1.85.0", Some(51992)), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146)), /// Allows `..` in tuple (struct) patterns. @@ -199,7 +199,7 @@ declare_features! ( (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), /// Allows using `efiapi`, `aapcs`, `sysv64` and `win64` as calling /// convention for functions with varargs. - (accepted, extended_varargs_abi_support, "CURRENT_RUSTC_VERSION", Some(100189)), + (accepted, extended_varargs_abi_support, "1.85.0", Some(100189)), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660)), /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 388ed9d08fa..9aa59375706 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -120,7 +120,7 @@ declare_features! ( /// Allows defining generators. (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")), /// An extension to the `generic_associated_types` feature, allowing incomplete features. - (removed, generic_associated_types_extended, "CURRENT_RUSTC_VERSION", Some(95451), + (removed, generic_associated_types_extended, "1.85.0", Some(95451), Some( "feature needs overhaul and reimplementation pending \ better implied higher-ranked implied bounds support" diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8cc4c18c02a..fb83487c939 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -333,7 +333,7 @@ declare_features! ( (unstable, hexagon_target_feature, "1.27.0", Some(44839)), (unstable, lahfsahf_target_feature, "1.78.0", Some(44839)), (unstable, loongarch_target_feature, "1.73.0", Some(44839)), - (unstable, m68k_target_feature, "CURRENT_RUSTC_VERSION", Some(134328)), + (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), @@ -344,7 +344,7 @@ declare_features! ( (unstable, sse4a_target_feature, "1.27.0", Some(44839)), (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), - (unstable, x87_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), + (unstable, x87_target_feature, "1.85.0", Some(44839)), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! @@ -380,11 +380,11 @@ declare_features! ( /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Enables experimental register support in inline assembly. - (unstable, asm_experimental_reg, "CURRENT_RUSTC_VERSION", Some(133416)), + (unstable, asm_experimental_reg, "1.85.0", Some(133416)), /// Allows using `label` operands in inline assembly. (unstable, asm_goto, "1.78.0", Some(119364)), /// Allows using `label` operands in inline assembly together with output operands. - (unstable, asm_goto_with_outputs, "CURRENT_RUSTC_VERSION", Some(119364)), + (unstable, asm_goto_with_outputs, "1.85.0", Some(119364)), /// Allows the `may_unwind` option in inline assembly. (unstable, asm_unwind, "1.58.0", Some(93334)), /// Allows users to enforce equality of associated constants `TraitImpl`. @@ -392,13 +392,13 @@ declare_features! ( /// Allows associated type defaults. (unstable, associated_type_defaults, "1.2.0", Some(29661)), /// Allows async functions to be called from `dyn Trait`. - (incomplete, async_fn_in_dyn_trait, "CURRENT_RUSTC_VERSION", Some(133119)), + (incomplete, async_fn_in_dyn_trait, "1.85.0", Some(133119)), /// Allows `#[track_caller]` on async functions. (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows `async` trait bound modifier. - (unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)), + (unstable, async_trait_bounds, "1.85.0", Some(62290)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg()]`. @@ -436,7 +436,7 @@ declare_features! ( /// Allows `const || {}` closures in const contexts. (incomplete, const_closures, "1.68.0", Some(106003)), /// Allows using `~const Destruct` bounds and calling drop impls in const contexts. - (unstable, const_destruct, "CURRENT_RUSTC_VERSION", Some(133214)), + (unstable, const_destruct, "1.85.0", Some(133214)), /// Allows `for _ in _` loops in const contexts. (unstable, const_for, "1.56.0", Some(87575)), /// Be more precise when looking for live drops in a const context. @@ -460,7 +460,7 @@ declare_features! ( (unstable, decl_macro, "1.17.0", Some(39412)), /// Allows the use of default values on struct definitions and the construction of struct /// literals with the functional update syntax without a base. - (unstable, default_field_values, "CURRENT_RUSTC_VERSION", Some(132162)), + (unstable, default_field_values, "1.85.0", Some(132162)), /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. @@ -510,7 +510,7 @@ declare_features! ( /// Allows registering static items globally, possibly across crates, to iterate over at runtime. (unstable, global_registration, "1.80.0", Some(125119)), /// Allows using guards in patterns. - (incomplete, guard_patterns, "CURRENT_RUSTC_VERSION", Some(129967)), + (incomplete, guard_patterns, "1.85.0", Some(129967)), /// Allows using `..=X` as a patterns in slices. (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), /// Allows `if let` guard in match arms. @@ -639,9 +639,9 @@ declare_features! ( /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), /// Allows using `unsafe<'a> &'a T` unsafe binder types. - (incomplete, unsafe_binders, "CURRENT_RUSTC_VERSION", Some(130516)), + (incomplete, unsafe_binders, "1.85.0", Some(130516)), /// Allows declaring fields `unsafe`. - (incomplete, unsafe_fields, "CURRENT_RUSTC_VERSION", Some(132922)), + (incomplete, unsafe_fields, "1.85.0", Some(132922)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. (incomplete, unsized_const_params, "1.82.0", Some(95174)), diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 0f66217b5cb..dcc1d0234d3 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2029,7 +2029,7 @@ impl + ?Sized, A: Allocator> Fn for Box { } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl + ?Sized, A: Allocator> AsyncFnOnce for Box { type Output = F::Output; type CallOnceFuture = F::CallOnceFuture; @@ -2040,7 +2040,7 @@ impl + ?Sized, A: Allocator> AsyncFnOnce } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl + ?Sized, A: Allocator> AsyncFnMut for Box { type CallRefFuture<'a> = F::CallRefFuture<'a> @@ -2053,7 +2053,7 @@ impl + ?Sized, A: Allocator> AsyncFnMut f } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl + ?Sized, A: Allocator> AsyncFn for Box { extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> { F::async_call(self, args) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index e6f39db9dce..21dfdd926e0 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: &T) -> Self { @@ -252,7 +252,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 { if let Some(align) = Alignment::new(align) { @@ -327,7 +327,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 +426,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 +489,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(n: usize) -> Result { // Reduce the amount of code we need to monomorphize per `T`. diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 84bbf985e8b..b43cf684215 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -752,10 +752,10 @@ pub struct BuildHasherDefault(marker::PhantomData H>); impl BuildHasherDefault { /// Creates a new BuildHasherDefault for Hasher `H`. - #[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 = "CURRENT_RUSTC_VERSION" + since = "1.85.0" )] pub const fn new() -> Self { BuildHasherDefault(marker::PhantomData) 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/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 58fb5be5812..284a58c7278 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -507,7 +507,7 @@ impl MaybeUninit { /// ``` #[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. 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() -> 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(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer @@ -484,7 +484,7 @@ pub const fn align_of() -> 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(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer @@ -725,7 +725,7 @@ pub unsafe fn uninitialized() -> 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(x: &mut T, y: &mut T) { // SAFETY: `&mut` guarantees these are typed readable and writable 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/mod.rs b/library/core/src/num/mod.rs index 1f5b8ce6c6e..67d219654b9 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -138,8 +138,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 +192,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/nonzero.rs b/library/core/src/num/nonzero.rs index a9294306b1b..926723b3dba 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1543,8 +1543,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/async_function.rs b/library/core/src/ops/async_function.rs index 0073afd4960..2ee243ea85e 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -5,7 +5,7 @@ use crate::marker::Tuple; /// /// 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"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] @@ -20,7 +20,7 @@ pub trait AsyncFn: AsyncFnMut { /// /// 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"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] @@ -42,7 +42,7 @@ pub trait AsyncFnMut: AsyncFnOnce { /// /// 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"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] @@ -68,7 +68,7 @@ mod impls { 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"))] + #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl AsyncFn for &F where F: AsyncFn, @@ -79,7 +79,7 @@ mod impls { } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl AsyncFnMut for &F where F: AsyncFn, @@ -95,7 +95,7 @@ mod impls { } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce for &'a F where F: AsyncFn, @@ -109,7 +109,7 @@ mod impls { } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl AsyncFnMut for &mut F where F: AsyncFnMut, @@ -125,7 +125,7 @@ mod impls { } #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] + #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce for &'a mut F where F: AsyncFnMut, 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/mod.rs b/library/core/src/ptr/mod.rs index a70af793004..3d9ad0706eb 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1009,7 +1009,7 @@ pub const fn slice_from_raw_parts_mut(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(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. @@ -2150,7 +2150,7 @@ pub fn addr_eq(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(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 *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..21bde4b8cc1 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -224,7 +224,7 @@ impl NonNull { /// } /// ``` #[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 { if !ptr.is_null() { @@ -1146,7 +1146,7 @@ impl NonNull { /// [`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) where T: Sized, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index f800e0d391c..8939e5072ba 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -913,7 +913,7 @@ impl [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) { 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/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 56d734ba2fb..f7d2eec9074 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -298,7 +298,7 @@ impl HashMap { #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] #[rustc_const_stable( feature = "const_collections_with_hasher", - since = "CURRENT_RUSTC_VERSION" + since = "1.85.0" )] pub const fn with_hasher(hash_builder: S) -> HashMap { HashMap { base: base::HashMap::with_hasher(hash_builder) } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index bcf6d6b4ccf..c1b794c58f1 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -390,7 +390,7 @@ impl HashSet { #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] #[rustc_const_stable( feature = "const_collections_with_hasher", - since = "CURRENT_RUSTC_VERSION" + since = "1.85.0" )] pub const fn with_hasher(hasher: S) -> HashSet { HashSet { base: base::HashSet::with_hasher(hasher) } diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 535236ff89a..11a29cdae62 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -622,7 +622,7 @@ impl Error for JoinPathsError { /// /// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`. /// -/// Before Rust CURRENT_RUSTC_VERSION, this function used to return the value of the 'HOME' environment variable +/// Before Rust 1.85.0, this function used to return the value of the 'HOME' environment variable /// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you` /// instead of `C:\Users\you`. /// diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 476c403c21f..38b72336617 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -339,7 +339,7 @@ pub enum ErrorKind { #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotSeekable, /// Filesystem quota or some other kind of quota was exceeded. - #[stable(feature = "io_error_quota_exceeded", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_quota_exceeded", since = "1.85.0")] QuotaExceeded, /// File larger than allowed or supported. /// @@ -364,7 +364,7 @@ pub enum ErrorKind { #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. - #[stable(feature = "io_error_crosses_devices", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_crosses_devices", since = "1.85.0")] CrossesDevices, /// Too many (hard) links to the same filesystem object. /// diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs index 22a364074c5..713e417e044 100644 --- a/library/std/src/prelude/common.rs +++ b/library/std/src/prelude/common.rs @@ -13,7 +13,7 @@ pub use crate::marker::{Send, Sized, Sync, Unpin}; #[doc(no_inline)] pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))] +#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] #[doc(no_inline)] pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}; diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 64349987fcf..4ec328208f0 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -169,12 +169,12 @@ pub mod rust_2021 { /// The 2024 version of the prelude of The Rust Standard Library. /// /// 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::*; - #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "prelude_2024", since = "1.85.0")] #[doc(no_inline)] pub use core::prelude::rust_2024::*; } diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md index f7e831dc8bd..c62ca9fd9ad 100644 --- a/src/doc/rustc/src/check-cfg.md +++ b/src/doc/rustc/src/check-cfg.md @@ -134,7 +134,7 @@ As of `2025-01-02T`, the list of known names is as follows: - `unix` - `windows` -> Starting with CURRENT_RUSTC_VERSION, the `test` cfg is consider to be a "userspace" config +> Starting with 1.85.0, the `test` cfg is consider to be a "userspace" config > despite being also set by `rustc` and should be managed by the build-system it-self. Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())` -- cgit 1.4.1-3-g733a5 From 2af3ba9a8aac4948596a98d4308b08317c005faa Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 8 Jan 2025 21:26:39 +0100 Subject: update cfg(bootstrap) --- compiler/rustc_ast/src/util/comments/tests.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- compiler/rustc_hir/src/tests.rs | 2 +- compiler/rustc_lint/src/tests.rs | 2 +- compiler/rustc_metadata/src/creader.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 +- compiler/rustc_parse/src/parser/tests.rs | 2 +- .../rustc_parse/src/parser/tokenstream/tests.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_span/src/edit_distance/tests.rs | 2 +- library/alloc/src/boxed.rs | 9 ++--- library/alloc/src/lib.rs | 1 - library/core/src/arch.rs | 1 - library/core/src/future/async_drop.rs | 5 +-- library/core/src/intrinsics/mod.rs | 32 +-------------- library/core/src/intrinsics/simd.rs | 1 - library/core/src/lib.rs | 1 - library/core/src/marker.rs | 36 +++++++---------- library/core/src/mem/transmutability.rs | 5 +-- library/core/src/ops/arith.rs | 14 +------ library/core/src/ops/async_function.rs | 24 ++++------- library/core/src/ops/deref.rs | 47 +--------------------- library/core/src/ops/drop.rs | 2 +- library/core/src/ptr/metadata.rs | 5 +-- library/core/src/ptr/non_null.rs | 1 - library/core/tests/ptr.rs | 2 +- library/std/src/prelude/common.rs | 3 +- src/bootstrap/src/core/builder/cargo.rs | 7 +--- src/bootstrap/src/lib.rs | 2 - 29 files changed, 49 insertions(+), 169 deletions(-) (limited to 'library/alloc/src') diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs index f88b534a0c1..7a87ccea62a 100644 --- a/compiler/rustc_ast/src/util/comments/tests.rs +++ b/compiler/rustc_ast/src/util/comments/tests.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] +#![allow(rustc::symbol_intern_string_literal)] use rustc_span::create_default_session_globals_then; diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index c8500098add..94746212138 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -692,7 +692,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) { .find(|feat| feat.gate_name == sym::generic_const_exprs) .map(|feat| feat.attr_sp) { - #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + #[allow(rustc::symbol_intern_string_literal)] sess.dcx().emit_err(errors::IncompatibleFeatures { spans: vec![gce_span], f1: Symbol::intern("-Znext-solver=globally"), diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 953e48a6d33..e0e63d183c6 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] +#![allow(rustc::symbol_intern_string_literal)] use rustc_data_structures::stable_hasher::Hash64; use rustc_span::def_id::{DefPathHash, StableCrateId}; diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs index 186dec5904b..f49301b0215 100644 --- a/compiler/rustc_lint/src/tests.rs +++ b/compiler/rustc_lint/src/tests.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] +#![allow(rustc::symbol_intern_string_literal)] use rustc_span::{Symbol, create_default_session_globals_then}; diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index c8715f94d5d..1ea075c2cb3 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -867,7 +867,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // First up we check for global allocators. Look at the crate graph here // and see what's a global allocator, including if we ourselves are a // global allocator. - #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + #[allow(rustc::symbol_intern_string_literal)] let this_crate = Symbol::intern("this crate"); let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c2b5e318bda..e02c4871f35 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -871,7 +871,7 @@ impl MetadataBlob { let def_kind = root.tables.def_kind.get(blob, item).unwrap(); let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob); - #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + #[allow(rustc::symbol_intern_string_literal)] let def_name = if item == CRATE_DEF_INDEX { kw::Crate } else { diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 3f8d66c2c95..c222aaa9a86 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] +#![allow(rustc::symbol_intern_string_literal)] use std::assert_matches::assert_matches; use std::io::prelude::*; diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs index 037b5b1a9de..aac75323ff3 100644 --- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs +++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] +#![allow(rustc::symbol_intern_string_literal)] use rustc_ast::token::{self, IdentIsRaw}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6ee02e9f47f..c47c3f64bf6 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3155,7 +3155,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + #[allow(rustc::symbol_intern_string_literal)] let existing_name = match &in_scope_lifetimes[..] { [] => Symbol::intern("'a"), [(existing, _)] => existing.name, diff --git a/compiler/rustc_span/src/edit_distance/tests.rs b/compiler/rustc_span/src/edit_distance/tests.rs index 9540f934d7e..8372856c0d3 100644 --- a/compiler/rustc_span/src/edit_distance/tests.rs +++ b/compiler/rustc_span/src/edit_distance/tests.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] +#![allow(rustc::symbol_intern_string_literal)] use super::*; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index dcc1d0234d3..1b5e44a9134 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2028,8 +2028,7 @@ impl + ?Sized, A: Allocator> Fn for Box { } } -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] +#[stable(feature = "async_closure", since = "1.85.0")] impl + ?Sized, A: Allocator> AsyncFnOnce for Box { type Output = F::Output; type CallOnceFuture = F::CallOnceFuture; @@ -2039,8 +2038,7 @@ impl + ?Sized, A: Allocator> AsyncFnOnce } } -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] +#[stable(feature = "async_closure", since = "1.85.0")] impl + ?Sized, A: Allocator> AsyncFnMut for Box { type CallRefFuture<'a> = F::CallRefFuture<'a> @@ -2052,8 +2050,7 @@ impl + ?Sized, A: Allocator> AsyncFnMut f } } -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] +#[stable(feature = "async_closure", since = "1.85.0")] impl + ?Sized, A: Allocator> AsyncFn for Box { extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> { F::async_call(self, args) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index aff90f5abb3..784af940769 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -91,7 +91,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(async_closure))] #![cfg_attr(test, feature(str_as_str))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] 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/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; } 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(_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(_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, U>( multiplier: T, multiplicand: T, @@ -3969,21 +3957,6 @@ pub const fn is_val_statically_known(_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(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(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(x: T, y: T, z: T) -> T; 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..b1e67e4e900 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -141,9 +141,8 @@ unsafe impl 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,9 +182,8 @@ 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 { // Empty. } @@ -819,9 +817,8 @@ impl StructuralPartialEq for PhantomData {} 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 +959,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 +971,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 +991,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 +1080,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 +1092,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/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 where 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 { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -95,18 +95,6 @@ pub trait Add { 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 2ee243ea85e..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 = "1.85.0"))] +#[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: AsyncFnMut { /// 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 = "1.85.0"))] +#[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: AsyncFnOnce { /// 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 = "1.85.0"))] +#[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 = "1.85.0"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl AsyncFn for &F where F: AsyncFn, @@ -78,8 +74,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl AsyncFnMut for &F where F: AsyncFn, @@ -94,8 +89,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce for &'a F where F: AsyncFn, @@ -108,8 +102,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl AsyncFnMut for &mut F where F: AsyncFnMut, @@ -124,8 +117,7 @@ mod impls { } } - #[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] - #[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] + #[stable(feature = "async_closure", since = "1.85.0")] impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce for &'a mut F where F: AsyncFnMut, 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 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 const Deref for &T { type Target = T; @@ -173,17 +161,6 @@ impl const Deref for &T { #[stable(feature = "rust1", since = "1.0.0")] impl !DerefMut for &T {} -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Deref for &mut T { - type Target = T; - - fn deref(&self) -> &T { - *self - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl const Deref for &mut T { type Target = T; @@ -282,7 +259,6 @@ impl 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 DerefMut for &mut T { - fn deref_mut(&mut self) -> &mut T { - *self - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl 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/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/non_null.rs b/library/core/src/ptr/non_null.rs index 21bde4b8cc1..7af26d521b3 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1556,7 +1556,6 @@ impl DispatchFromDyn> for NonNull where T: U unsafe impl PinCoerceUnsized for NonNull {} #[unstable(feature = "pointer_like_trait", issue = "none")] -#[cfg(not(bootstrap))] impl core::marker::PointerLike for NonNull {} #[stable(feature = "nonnull", since = "1.25.0")] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index e6825d8e39e..7cefb615d03 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -304,7 +304,7 @@ fn test_const_nonnull_new() { #[test] #[cfg(unix)] // printf may not be available on other platforms #[allow(deprecated)] // For SipHasher -#[cfg_attr(not(bootstrap), allow(unpredictable_function_pointer_comparisons))] +#[allow(unpredictable_function_pointer_comparisons)] pub fn test_variadic_fnptr() { use core::ffi; use core::hash::{Hash, SipHasher}; diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs index 713e417e044..0f2d8334fca 100644 --- a/library/std/src/prelude/common.rs +++ b/library/std/src/prelude/common.rs @@ -12,8 +12,7 @@ pub use crate::marker::{Send, Sized, Sync, Unpin}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; -#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))] -#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "1.85.0"))] +#[stable(feature = "async_closure", since = "1.85.0")] #[doc(no_inline)] pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}; diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 432fbb8d636..c121543462c 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -624,8 +624,6 @@ impl Builder<'_> { // get warnings about it being unexpected. hostflags.arg("-Zunstable-options"); hostflags.arg("--check-cfg=cfg(bootstrap)"); - // #[cfg(bootstrap)] as we are transition `test` to userspace cfg - hostflags.arg("--check-cfg=cfg(test)"); // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`, // but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See @@ -1206,10 +1204,7 @@ impl Builder<'_> { // so that it'll be available when downstream consumers of std try to use it. rustflags.arg("-Zinline-mir-preserve-debug"); - // FIXME: always pass this after the next `#[cfg(bootstrap)]` update. - if compiler.stage != 0 { - rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions"); - } + rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions"); } Cargo { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 8405c22aff0..4cc812829f9 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -77,8 +77,6 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; #[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (None, "bootstrap", None), - // #[cfg(bootstrap)] to be removed when Cargo is updated - (None, "test", None), (Some(Mode::Rustc), "llvm_enzyme", None), (Some(Mode::Codegen), "llvm_enzyme", None), (Some(Mode::ToolRustc), "llvm_enzyme", None), -- cgit 1.4.1-3-g733a5 From eb917ea24deeeb92ab76fcb215aac4c7a567644d Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 8 Jan 2025 21:18:46 +0000 Subject: Remove some unnecessary `.into()` calls --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 6 +++--- compiler/rustc_parse/src/parser/tests.rs | 6 ++---- compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 4 ++-- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/std/src/thread/mod.rs | 2 +- 7 files changed, 11 insertions(+), 13 deletions(-) (limited to 'library/alloc/src') diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 81a5e9ee90d..dd6adb17c5e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1120,7 +1120,7 @@ fn check_type_defn<'tcx>( } else { // Evaluate the constant proactively, to emit an error if the constant has // an unconditional error. We only do so if the const has no type params. - let _ = tcx.const_eval_poly(def_id.into()); + let _ = tcx.const_eval_poly(def_id); } } let field_id = field.did.expect_local(); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e74fb9d92e9..31ba8619c36 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1304,9 +1304,9 @@ impl UnreachablePub { cx.effective_visibilities.effective_vis(def_id).map(|effective_vis| { effective_vis.at_level(rustc_middle::middle::privacy::Level::Reachable) }) - && let parent_parent = cx.tcx.parent_module_from_def_id( - cx.tcx.parent_module_from_def_id(def_id.into()).into(), - ) + && let parent_parent = cx + .tcx + .parent_module_from_def_id(cx.tcx.parent_module_from_def_id(def_id).into()) && *restricted_did == parent_parent.to_local_def_id() && !restricted_did.to_def_id().is_crate_root() { diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 3f8d66c2c95..b810bb4e3bb 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2366,8 +2366,7 @@ fn string_to_tts_1() { token::Ident(sym::i32, IdentIsRaw::No), sp(8, 11), ), - ]) - .into(), + ]), ), TokenTree::Delimited( DelimSpan::from_pair(sp(13, 14), sp(18, 19)), @@ -2383,8 +2382,7 @@ fn string_to_tts_1() { ), // `Alone` because the `;` is followed by whitespace. TokenTree::token_alone(token::Semi, sp(16, 17)), - ]) - .into(), + ]), ), ]); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 15eb5d74cbf..446f9eaa348 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -79,7 +79,7 @@ pub fn is_const_evaluatable<'tcx>( Err( EvaluateConstErr::EvaluationFailure(e) | EvaluateConstErr::InvalidConstParamTy(e), - ) => Err(NotConstEvaluatable::Error(e.into())), + ) => Err(NotConstEvaluatable::Error(e)), Ok(_) => Ok(()), } } @@ -140,7 +140,7 @@ pub fn is_const_evaluatable<'tcx>( } Err( EvaluateConstErr::EvaluationFailure(e) | EvaluateConstErr::InvalidConstParamTy(e), - ) => Err(NotConstEvaluatable::Error(e.into())), + ) => Err(NotConstEvaluatable::Error(e)), Ok(_) => Ok(()), } } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index e014404eff3..08a7b325798 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1789,7 +1789,7 @@ impl Rc { /// let x: Rc<&str> = Rc::new("Hello, world!"); /// { /// let s = String::from("Oh, no!"); - /// let mut y: Rc<&str> = x.clone().into(); + /// let mut y: Rc<&str> = x.clone(); /// unsafe { /// // this is Undefined Behavior, because x's inner type /// // is &'long str, not &'short str diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b34a6d3f660..30761739dbf 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2468,7 +2468,7 @@ impl Arc { /// let x: Arc<&str> = Arc::new("Hello, world!"); /// { /// let s = String::from("Oh, no!"); - /// let mut y: Arc<&str> = x.clone().into(); + /// let mut y: Arc<&str> = x.clone(); /// unsafe { /// // this is Undefined Behavior, because x's inner type /// // is &'long str, not &'short str diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 85ee369ca2b..b6ee00a253a 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -502,7 +502,7 @@ impl Builder { let id = ThreadId::new(); let my_thread = match name { - Some(name) => Thread::new(id, name.into()), + Some(name) => Thread::new(id, name), None => Thread::new_unnamed(id), }; -- cgit 1.4.1-3-g733a5 From 6f2a78345ee7f55c5ce33fd7b9804c665c646dd2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 7 Jan 2025 19:35:37 -0800 Subject: Update a bunch of library types for MCP807 This greatly reduces the number of places that actually use the `rustc_layout_scalar_valid_range_*` attributes down to just 3: ``` library/core\src\ptr\non_null.rs 68:#[rustc_layout_scalar_valid_range_start(1)] library/core\src\num\niche_types.rs 19: #[rustc_layout_scalar_valid_range_start($low)] 20: #[rustc_layout_scalar_valid_range_end($high)] ``` Everything else -- PAL Nanoseconds, alloc's `Cap`, niched FDs, etc -- all just wrap those `niche_types` types. --- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 46 ++++--- library/core/src/num/mod.rs | 4 + library/core/src/num/niche_types.rs | 162 +++++++++++++++++++++++++ library/core/src/num/nonzero.rs | 31 +---- library/core/src/time.rs | 96 +++++++-------- library/std/src/lib.rs | 1 + library/std/src/os/fd/owned.rs | 34 +++--- library/std/src/os/solid/io.rs | 27 ++--- library/std/src/os/windows/io/socket.rs | 39 +++--- library/std/src/sys/pal/solid/fs.rs | 14 +-- library/std/src/sys/pal/unix/time.rs | 33 +++-- tests/codegen/vec-in-place.rs | 54 +++++++-- tests/codegen/vec_pop_push_noop.rs | 3 - tests/debuginfo/strings-and-strs.rs | 2 +- tests/ui/lint/invalid_value.stderr | 10 +- tests/ui/print_type_sizes/niche-filling.stdout | 2 +- 17 files changed, 345 insertions(+), 214 deletions(-) create mode 100644 library/core/src/num/niche_types.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 784af940769..a4c3b7dd1b1 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -142,6 +142,7 @@ #![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] +#![feature(temporary_niche_types)] #![feature(trusted_fused)] #![feature(trusted_len)] #![feature(trusted_random_access)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index e93ff2f9023..ad86bf4bf07 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -33,21 +33,15 @@ enum AllocInit { Zeroed, } -#[repr(transparent)] -#[cfg_attr(target_pointer_width = "16", rustc_layout_scalar_valid_range_end(0x7fff))] -#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0x7fff_ffff))] -#[cfg_attr(target_pointer_width = "64", rustc_layout_scalar_valid_range_end(0x7fff_ffff_ffff_ffff))] -struct Cap(usize); +type Cap = core::num::niche_types::UsizeNoHighBit; -impl Cap { - const ZERO: Cap = unsafe { Cap(0) }; +const ZERO_CAP: Cap = unsafe { Cap::new_unchecked(0) }; - /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. - /// - /// # Safety: cap must be <= `isize::MAX`. - unsafe fn new(cap: usize) -> Self { - if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } } - } +/// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. +/// +/// # Safety: cap must be <= `isize::MAX`. +unsafe fn new_cap(cap: usize) -> Cap { + if T::IS_ZST { ZERO_CAP } else { unsafe { Cap::new_unchecked(cap) } } } /// A low-level utility for more ergonomically allocating, reallocating, and deallocating @@ -257,7 +251,7 @@ impl RawVec { // SAFETY: Precondition passed to the caller unsafe { let ptr = ptr.cast(); - let capacity = Cap::new::(capacity); + let capacity = new_cap::(capacity); Self { inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc), _marker: PhantomData, @@ -275,7 +269,7 @@ impl RawVec { // SAFETY: Precondition passed to the caller unsafe { let ptr = ptr.cast(); - let capacity = Cap::new::(capacity); + let capacity = new_cap::(capacity); Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData } } } @@ -410,7 +404,7 @@ impl RawVecInner { const fn new_in(alloc: A, align: usize) -> Self { let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. - Self { ptr, cap: Cap::ZERO, alloc } + Self { ptr, cap: ZERO_CAP, alloc } } #[cfg(not(no_global_oom_handling))] @@ -483,7 +477,11 @@ impl RawVecInner { // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::()`. - Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }) + Ok(Self { + ptr: Unique::from(ptr.cast()), + cap: unsafe { Cap::new_unchecked(capacity) }, + alloc, + }) } #[inline] @@ -508,7 +506,7 @@ impl RawVecInner { #[inline] const fn capacity(&self, elem_size: usize) -> usize { - if elem_size == 0 { usize::MAX } else { self.cap.0 } + if elem_size == 0 { usize::MAX } else { self.cap.as_inner() } } #[inline] @@ -518,7 +516,7 @@ impl RawVecInner { #[inline] fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull, Layout)> { - if elem_layout.size() == 0 || self.cap.0 == 0 { + if elem_layout.size() == 0 || self.cap.as_inner() == 0 { None } else { // We could use Layout::array here which ensures the absence of isize and usize overflows @@ -526,7 +524,7 @@ impl RawVecInner { // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. unsafe { - let alloc_size = elem_layout.size().unchecked_mul(self.cap.0); + let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner()); let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); Some((self.ptr.into(), layout)) } @@ -562,7 +560,7 @@ impl RawVecInner { #[inline] #[track_caller] fn grow_one(&mut self, elem_layout: Layout) { - if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) { + if let Err(err) = self.grow_amortized(self.cap.as_inner(), 1, elem_layout) { handle_error(err); } } @@ -627,7 +625,7 @@ impl RawVecInner { // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / mem::size_of::()`. self.ptr = Unique::from(ptr.cast()); - self.cap = unsafe { Cap(cap) }; + self.cap = unsafe { Cap::new_unchecked(cap) }; } fn grow_amortized( @@ -650,7 +648,7 @@ impl RawVecInner { // This guarantees exponential growth. The doubling cannot overflow // because `cap <= isize::MAX` and the type of `cap` is `usize`. - let cap = cmp::max(self.cap.0 * 2, required_cap); + let cap = cmp::max(self.cap.as_inner() * 2, required_cap); let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap); let new_layout = layout_array(cap, elem_layout)?; @@ -719,7 +717,7 @@ impl RawVecInner { unsafe { self.alloc.deallocate(ptr, layout) }; self.ptr = unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; - self.cap = Cap::ZERO; + self.cap = ZERO_CAP; } else { let ptr = unsafe { // Layout cannot overflow here because it would have diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 67d219654b9..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; diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs new file mode 100644 index 00000000000..e4caf8a104c --- /dev/null +++ b/library/core/src/num/niche_types.rs @@ -0,0 +1,162 @@ +#![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 { + #[inline] + pub const unsafe fn new_unchecked(val: $int) -> Self { + // SAFETY: same precondition + 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 . + 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 { + Some(Ord::cmp(self, other)) + } + } + + impl Hash for $name { + // Required method + fn hash(&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 = ::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 926723b3dba..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 . - #[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; } )+ }; 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 { 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 { 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 { // 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 { 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") } } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2f8f5c5c581..022bbab1012 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -357,6 +357,7 @@ #![feature(str_internals)] #![feature(strict_provenance_atomic_ptr)] #![feature(sync_unsafe_cell)] +#![feature(temporary_niche_types)] #![feature(ub_checks)] #![feature(used_with_arg)] // tidy-alphabetical-end diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index abb13b75f50..1e814eca3c1 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -11,6 +11,8 @@ use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, fs, io}; +type ValidRawFd = core::num::niche_types::NotAllOnes; + /// A borrowed file descriptor. /// /// This has a lifetime parameter to tie it to the lifetime of something that owns the file @@ -32,15 +34,10 @@ use crate::{fmt, fs, io}; /// instead, but this is not supported on all platforms. #[derive(Copy, Clone)] #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] #[rustc_nonnull_optimization_guaranteed] #[stable(feature = "io_safety", since = "1.63.0")] pub struct BorrowedFd<'fd> { - fd: RawFd, + fd: ValidRawFd, _phantom: PhantomData<&'fd OwnedFd>, } @@ -56,15 +53,10 @@ pub struct BorrowedFd<'fd> { /// /// You can use [`AsFd::as_fd`] to obtain a [`BorrowedFd`]. #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] #[rustc_nonnull_optimization_guaranteed] #[stable(feature = "io_safety", since = "1.63.0")] pub struct OwnedFd { - fd: RawFd, + fd: ValidRawFd, } impl BorrowedFd<'_> { @@ -80,7 +72,8 @@ impl BorrowedFd<'_> { pub const unsafe fn borrow_raw(fd: RawFd) -> Self { assert!(fd != u32::MAX as RawFd); // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { Self { fd, _phantom: PhantomData } } + let fd = unsafe { ValidRawFd::new_unchecked(fd) }; + Self { fd, _phantom: PhantomData } } } @@ -130,7 +123,7 @@ impl BorrowedFd<'_> { impl AsRawFd for BorrowedFd<'_> { #[inline] fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd.as_inner() } } @@ -138,7 +131,7 @@ impl AsRawFd for BorrowedFd<'_> { impl AsRawFd for OwnedFd { #[inline] fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd.as_inner() } } @@ -146,7 +139,7 @@ impl AsRawFd for OwnedFd { impl IntoRawFd for OwnedFd { #[inline] fn into_raw_fd(self) -> RawFd { - ManuallyDrop::new(self).fd + ManuallyDrop::new(self).fd.as_inner() } } @@ -164,7 +157,8 @@ impl FromRawFd for OwnedFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { assert_ne!(fd, u32::MAX as RawFd); // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { Self { fd } } + let fd = unsafe { ValidRawFd::new_unchecked(fd) }; + Self { fd } } } @@ -187,12 +181,12 @@ impl Drop for OwnedFd { #[cfg(not(target_os = "hermit"))] { #[cfg(unix)] - crate::sys::fs::debug_assert_fd_is_open(self.fd); + crate::sys::fs::debug_assert_fd_is_open(self.fd.as_inner()); - let _ = libc::close(self.fd); + let _ = libc::close(self.fd.as_inner()); } #[cfg(target_os = "hermit")] - let _ = hermit_abi::close(self.fd); + let _ = hermit_abi::close(self.fd.as_inner()); } } } diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 2d18f339615..b8601b533fe 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -54,6 +54,9 @@ use crate::{fmt, net, sys}; /// Raw file descriptors. pub type RawFd = i32; +// The max of this is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. +type ValidRawFd = core::num::niche_types::NotAllOnes; + /// A borrowed SOLID Sockets file descriptor. /// /// This has a lifetime parameter to tie it to the lifetime of something that @@ -69,12 +72,9 @@ pub type RawFd = i32; /// socket, which is then borrowed under the same lifetime. #[derive(Copy, Clone)] #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] #[rustc_nonnull_optimization_guaranteed] pub struct BorrowedFd<'socket> { - fd: RawFd, + fd: ValidRawFd, _phantom: PhantomData<&'socket OwnedFd>, } @@ -87,12 +87,9 @@ pub struct BorrowedFd<'socket> { /// an argument, it is not captured or consumed, and it never has the value /// `SOLID_NET_INVALID_FD`. #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] #[rustc_nonnull_optimization_guaranteed] pub struct OwnedFd { - fd: RawFd, + fd: ValidRawFd, } impl BorrowedFd<'_> { @@ -108,7 +105,8 @@ impl BorrowedFd<'_> { assert!(fd != -1 as RawFd); // SAFETY: we just asserted that the value is in the valid range and // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { Self { fd, _phantom: PhantomData } } + let fd = unsafe { ValidRawFd::new_unchecked(fd) }; + Self { fd, _phantom: PhantomData } } } @@ -132,21 +130,21 @@ impl BorrowedFd<'_> { impl AsRawFd for BorrowedFd<'_> { #[inline] fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd.as_inner() } } impl AsRawFd for OwnedFd { #[inline] fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd.as_inner() } } impl IntoRawFd for OwnedFd { #[inline] fn into_raw_fd(self) -> RawFd { - ManuallyDrop::new(self).fd + ManuallyDrop::new(self).fd.as_inner() } } @@ -162,14 +160,15 @@ impl FromRawFd for OwnedFd { assert_ne!(fd, -1 as RawFd); // SAFETY: we just asserted that the value is in the valid range and // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { Self { fd } } + let fd = unsafe { ValidRawFd::new_unchecked(fd) }; + Self { fd } } } impl Drop for OwnedFd { #[inline] fn drop(&mut self) { - unsafe { sys::net::netc::close(self.fd) }; + unsafe { sys::net::netc::close(self.fd.as_inner()) }; } } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index c6d7bad9440..6e13a8b502a 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -9,6 +9,9 @@ use crate::mem::{self, ManuallyDrop}; use crate::sys::cvt; use crate::{fmt, io, sys}; +// The max here is -2, in two's complement. -1 is `INVALID_SOCKET`. +type ValidRawSocket = core::num::niche_types::NotAllOnes; + /// A borrowed socket. /// /// This has a lifetime parameter to tie it to the lifetime of something that @@ -24,17 +27,10 @@ use crate::{fmt, io, sys}; /// socket, which is then borrowed under the same lifetime. #[derive(Copy, Clone)] #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -// This is -2, in two's complement. -1 is `INVALID_SOCKET`. -#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] -#[cfg_attr( - target_pointer_width = "64", - rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE) -)] #[rustc_nonnull_optimization_guaranteed] #[stable(feature = "io_safety", since = "1.63.0")] pub struct BorrowedSocket<'socket> { - socket: RawSocket, + socket: ValidRawSocket, _phantom: PhantomData<&'socket OwnedSocket>, } @@ -47,17 +43,10 @@ pub struct BorrowedSocket<'socket> { /// argument or returned as an owned value, and it never has the value /// `INVALID_SOCKET`. #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(0)] -// This is -2, in two's complement. -1 is `INVALID_SOCKET`. -#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] -#[cfg_attr( - target_pointer_width = "64", - rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE) -)] #[rustc_nonnull_optimization_guaranteed] #[stable(feature = "io_safety", since = "1.63.0")] pub struct OwnedSocket { - socket: RawSocket, + socket: ValidRawSocket, } impl BorrowedSocket<'_> { @@ -73,7 +62,8 @@ impl BorrowedSocket<'_> { #[stable(feature = "io_safety", since = "1.63.0")] pub const unsafe fn borrow_raw(socket: RawSocket) -> Self { assert!(socket != sys::c::INVALID_SOCKET as RawSocket); - unsafe { Self { socket, _phantom: PhantomData } } + let socket = unsafe { ValidRawSocket::new_unchecked(socket) }; + Self { socket, _phantom: PhantomData } } } @@ -172,7 +162,7 @@ fn last_error() -> io::Error { impl AsRawSocket for BorrowedSocket<'_> { #[inline] fn as_raw_socket(&self) -> RawSocket { - self.socket + self.socket.as_inner() } } @@ -180,7 +170,7 @@ impl AsRawSocket for BorrowedSocket<'_> { impl AsRawSocket for OwnedSocket { #[inline] fn as_raw_socket(&self) -> RawSocket { - self.socket + self.socket.as_inner() } } @@ -188,7 +178,7 @@ impl AsRawSocket for OwnedSocket { impl IntoRawSocket for OwnedSocket { #[inline] fn into_raw_socket(self) -> RawSocket { - ManuallyDrop::new(self).socket + ManuallyDrop::new(self).socket.as_inner() } } @@ -196,10 +186,9 @@ impl IntoRawSocket for OwnedSocket { impl FromRawSocket for OwnedSocket { #[inline] unsafe fn from_raw_socket(socket: RawSocket) -> Self { - unsafe { - debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket); - Self { socket } - } + debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket); + let socket = unsafe { ValidRawSocket::new_unchecked(socket) }; + Self { socket } } } @@ -208,7 +197,7 @@ impl Drop for OwnedSocket { #[inline] fn drop(&mut self) { unsafe { - let _ = sys::c::closesocket(self.socket as sys::c::SOCKET); + let _ = sys::c::closesocket(self.socket.as_inner() as sys::c::SOCKET); } } } diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs index 04dd10ad806..fa2e470d6b6 100644 --- a/library/std/src/sys/pal/solid/fs.rs +++ b/library/std/src/sys/pal/solid/fs.rs @@ -12,15 +12,12 @@ use crate::sys::unsupported; pub use crate::sys_common::fs::exists; use crate::sys_common::ignore_notfound; +type CIntNotMinusOne = core::num::niche_types::NotAllOnes; + /// A file descriptor. #[derive(Clone, Copy)] -#[rustc_layout_scalar_valid_range_start(0)] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] struct FileDesc { - fd: c_int, + fd: CIntNotMinusOne, } impl FileDesc { @@ -29,12 +26,13 @@ impl FileDesc { assert_ne!(fd, -1i32); // Safety: we just asserted that the value is in the valid range and // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { FileDesc { fd } } + let fd = unsafe { CIntNotMinusOne::new_unchecked(fd) }; + FileDesc { fd } } #[inline] fn raw(&self) -> c_int { - self.fd + self.fd.as_inner() } } diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index 343864d0b3f..e224980e95f 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -1,3 +1,5 @@ +use core::num::niche_types::Nanoseconds; + use crate::time::Duration; use crate::{fmt, io}; @@ -15,12 +17,6 @@ pub(in crate::sys) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec { tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64, }; -#[derive(Copy, Clone, 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); - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SystemTime { pub(crate) t: Timespec, @@ -59,14 +55,14 @@ impl fmt::Debug for SystemTime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SystemTime") .field("tv_sec", &self.t.tv_sec) - .field("tv_nsec", &self.t.tv_nsec.0) + .field("tv_nsec", &self.t.tv_nsec) .finish() } } impl Timespec { const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec { - Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } } + Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } } } pub const fn zero() -> Timespec { @@ -147,12 +143,15 @@ impl Timespec { // // Ideally this code could be rearranged such that it more // directly expresses the lower-cost behavior we want from it. - let (secs, nsec) = if self.tv_nsec.0 >= other.tv_nsec.0 { - ((self.tv_sec - other.tv_sec) as u64, self.tv_nsec.0 - other.tv_nsec.0) + let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() { + ( + (self.tv_sec - other.tv_sec) as u64, + self.tv_nsec.as_inner() - other.tv_nsec.as_inner(), + ) } else { ( (self.tv_sec - other.tv_sec - 1) as u64, - self.tv_nsec.0 + (NSEC_PER_SEC as u32) - other.tv_nsec.0, + self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(), ) }; @@ -170,7 +169,7 @@ impl Timespec { // Nano calculations can't overflow because nanos are <1B which fit // in a u32. - let mut nsec = other.subsec_nanos() + self.tv_nsec.0; + let mut nsec = other.subsec_nanos() + self.tv_nsec.as_inner(); if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; @@ -182,7 +181,7 @@ impl Timespec { let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. - let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32; + let mut nsec = self.tv_nsec.as_inner() as i32 - other.subsec_nanos() as i32; if nsec < 0 { nsec += NSEC_PER_SEC as i32; secs = secs.checked_sub(1)?; @@ -194,7 +193,7 @@ impl Timespec { pub fn to_timespec(&self) -> Option { Some(libc::timespec { tv_sec: self.tv_sec.try_into().ok()?, - tv_nsec: self.tv_nsec.0.try_into().ok()?, + tv_nsec: self.tv_nsec.as_inner().try_into().ok()?, }) } @@ -203,7 +202,7 @@ impl Timespec { #[cfg(target_os = "nto")] pub(in crate::sys) fn to_timespec_capped(&self) -> Option { // Check if timeout in nanoseconds would fit into an u64 - if (self.tv_nsec.0 as u64) + if (self.tv_nsec.as_inner() as u64) .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?) .is_none() { @@ -219,7 +218,7 @@ impl Timespec { not(target_arch = "riscv32") ))] pub fn to_timespec64(&self) -> __timespec64 { - __timespec64::new(self.tv_sec, self.tv_nsec.0 as _) + __timespec64::new(self.tv_sec, self.tv_nsec.as_inner() as _) } } @@ -293,7 +292,7 @@ impl fmt::Debug for Instant { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Instant") .field("tv_sec", &self.t.tv_sec) - .field("tv_nsec", &self.t.tv_nsec.0) + .field("tv_nsec", &self.t.tv_nsec) .finish() } } diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs index 33de0913f77..e835a7ef69b 100644 --- a/tests/codegen/vec-in-place.rs +++ b/tests/codegen/vec-in-place.rs @@ -37,8 +37,11 @@ pub struct Baz { #[no_mangle] pub fn vec_iterator_cast_primitive(vec: Vec) -> Vec { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| e as u8).collect() @@ -48,8 +51,11 @@ pub fn vec_iterator_cast_primitive(vec: Vec) -> Vec { #[no_mangle] pub fn vec_iterator_cast_wrapper(vec: Vec) -> Vec> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| Wrapper(e)).collect() @@ -76,8 +82,11 @@ pub fn vec_iterator_cast_signed_nested(vec: Vec>) -> Vec> { #[no_mangle] pub fn vec_iterator_cast_unwrap(vec: Vec>) -> Vec { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| e.0).collect() @@ -87,8 +96,11 @@ pub fn vec_iterator_cast_unwrap(vec: Vec>) -> Vec { #[no_mangle] pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() @@ -98,8 +110,11 @@ pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec { #[no_mangle] pub fn vec_iterator_cast_deaggregate_tra(vec: Vec) -> Vec<[u64; 4]> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call @@ -114,8 +129,11 @@ pub fn vec_iterator_cast_deaggregate_tra(vec: Vec) -> Vec<[u64; 4]> { #[no_mangle] pub fn vec_iterator_cast_deaggregate_fold(vec: Vec) -> Vec<[u64; 4]> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call @@ -138,6 +156,12 @@ pub fn vec_iterator_cast_unwrap_drop(vec: Vec>) -> Vec { // CHECK-NOT: call // CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = udiv + // CHECK: call + // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} + // CHECK-NOT: call + // CHECK-NOT: %{{.*}} = mul + // CHECK-NOT: %{{.*}} = udiv vec.into_iter().map(|Wrapper(e)| e).collect() } @@ -154,6 +178,12 @@ pub fn vec_iterator_cast_wrap_drop(vec: Vec) -> Vec> { // CHECK-NOT: call // CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = udiv + // CHECK: call + // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} + // CHECK-NOT: call + // CHECK-NOT: %{{.*}} = mul + // CHECK-NOT: %{{.*}} = udiv // CHECK: ret void vec.into_iter().map(Wrapper).collect() diff --git a/tests/codegen/vec_pop_push_noop.rs b/tests/codegen/vec_pop_push_noop.rs index a8ad5b6f1a3..4821e840884 100644 --- a/tests/codegen/vec_pop_push_noop.rs +++ b/tests/codegen/vec_pop_push_noop.rs @@ -12,9 +12,6 @@ pub fn noop(v: &mut Vec) { // CHECK-NOT: call // CHECK: tail call void @llvm.assume // CHECK-NOT: grow_one - // llvm-pre-19: call - // llvm-pre-19-same: void @llvm.assume - // llvm-pre-19-NOT: grow_one // CHECK-NOT: call // CHECK: {{ret|[}]}} if let Some(x) = v.pop() { diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 3d6589db34b..543e74e1744 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -7,7 +7,7 @@ // gdb-command:run // gdb-command:print plain_string -// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} +// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} // gdb-command:print plain_str // gdb-check:$2 = "Hello" diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr index b4e7421829f..cc6a2a1c8e5 100644 --- a/tests/ui/lint/invalid_value.stderr +++ b/tests/ui/lint/invalid_value.stderr @@ -323,7 +323,7 @@ LL | let _val: (NonZero, i32) = mem::zeroed(); | ^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: `std::num::NonZero` must be non-null - = note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null + = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null error: the type `(NonZero, i32)` does not permit being left uninitialized --> $DIR/invalid_value.rs:95:41 @@ -332,7 +332,7 @@ LL | let _val: (NonZero, i32) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: `std::num::NonZero` must be non-null - = note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null + = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null = note: integers must be initialized error: the type `*const dyn Send` does not permit zero-initialization @@ -415,7 +415,7 @@ note: because `std::num::NonZero` must be non-null (in this field of the on | LL | Banana(NonZero), | ^^^^^^^^^^^^ - = note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null + = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null error: the type `OneFruitNonZero` does not permit being left uninitialized --> $DIR/invalid_value.rs:107:37 @@ -429,7 +429,7 @@ note: because `std::num::NonZero` must be non-null (in this field of the on | LL | Banana(NonZero), | ^^^^^^^^^^^^ - = note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null + = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null = note: integers must be initialized error: the type `bool` does not permit being left uninitialized @@ -602,7 +602,7 @@ LL | let _val: NonZero = mem::transmute(0); | ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: `std::num::NonZero` must be non-null - = note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null + = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null error: the type `NonNull` does not permit zero-initialization --> $DIR/invalid_value.rs:156:34 diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout index eeb5de53241..70612490a47 100644 --- a/tests/ui/print_type_sizes/niche-filling.stdout +++ b/tests/ui/print_type_sizes/niche-filling.stdout @@ -68,7 +68,7 @@ print-type-size type: `Union2, u32>`: 4 bytes, alignment: print-type-size variant `Union2`: 4 bytes print-type-size field `.a`: 4 bytes print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes -print-type-size type: `core::num::nonzero::private::NonZeroU32Inner`: 4 bytes, alignment: 4 bytes +print-type-size type: `core::num::niche_types::NonZeroU32Inner`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `std::num::NonZero`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes -- cgit 1.4.1-3-g733a5 From 4426e9a3c260e329f51c94e2b231f72574271f0b Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 10 Jan 2025 18:48:48 +0100 Subject: alloc: remove unsound `IsZero` for raw pointers Fixes #135338 --- library/alloc/src/vec/is_zero.rs | 15 ++------------- library/alloc/tests/vec.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index ba57d940d8c..a3ddd6f6e23 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -40,19 +40,8 @@ impl_is_zero!(char, |x| x == '\0'); impl_is_zero!(f32, |x: f32| x.to_bits() == 0); impl_is_zero!(f64, |x: f64| x.to_bits() == 0); -unsafe impl IsZero for *const T { - #[inline] - fn is_zero(&self) -> bool { - (*self).is_null() - } -} - -unsafe impl IsZero for *mut T { - #[inline] - fn is_zero(&self) -> bool { - (*self).is_null() - } -} +// `IsZero` cannot be soundly implemented for pointers because of provenance +// (see #135338). unsafe impl IsZero for [T; N] { #[inline] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 2e654d3d1ff..b24daec2968 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2742,3 +2742,13 @@ fn max_swap_remove() { let mut v = vec![0]; v.swap_remove(usize::MAX); } + +// Regression test for #135338 +#[test] +fn vec_null_ptr_roundtrip() { + let ptr = std::ptr::from_ref(&42); + let zero = ptr.with_addr(0); + let roundtripped = vec![zero; 1].pop().unwrap(); + let new = roundtripped.with_addr(ptr.addr()); + unsafe { new.read() }; +} -- cgit 1.4.1-3-g733a5 From 9ab77f1ccb6baa931afeacf54594a4a2c7754332 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 10 Jan 2025 22:41:48 +0100 Subject: Use `NonNull::without_provenance` within the standard library This API removes the need for several `unsafe` blocks, and leads to clearer code. --- library/alloc/src/lib.rs | 1 + library/alloc/src/rc.rs | 15 +++------------ library/alloc/src/sync.rs | 15 +++------------ library/core/src/alloc/layout.rs | 3 +-- library/std/src/io/error/repr_bitpacked.rs | 7 ++++--- library/std/src/lib.rs | 1 + 6 files changed, 13 insertions(+), 29 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 784af940769..b3f13cbedbb 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -126,6 +126,7 @@ #![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(nonnull_provenance)] #![feature(panic_internals)] #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 08a7b325798..9256cb0703a 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -252,6 +252,7 @@ use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; +use core::num::NonZeroUsize; use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] @@ -3027,12 +3028,7 @@ impl Weak { #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] #[must_use] pub const fn new() -> Weak { - Weak { - ptr: unsafe { - NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) - }, - alloc: Global, - } + Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global } } } @@ -3054,12 +3050,7 @@ impl Weak { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn new_in(alloc: A) -> Weak { - Weak { - ptr: unsafe { - NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) - }, - alloc, - } + Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 30761739dbf..11e7128e677 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -18,6 +18,7 @@ use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; +use core::num::NonZeroUsize; use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::{Pin, PinCoerceUnsized}; @@ -2687,12 +2688,7 @@ impl Weak { #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] #[must_use] pub const fn new() -> Weak { - Weak { - ptr: unsafe { - NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) - }, - alloc: Global, - } + Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global } } } @@ -2717,12 +2713,7 @@ impl Weak { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn new_in(alloc: A) -> Weak { - Weak { - ptr: unsafe { - NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) - }, - alloc, - } + Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc } } } diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 21dfdd926e0..17f4d68867e 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -233,8 +233,7 @@ impl Layout { #[must_use] #[inline] pub const fn dangling(&self) -> NonNull { - // SAFETY: align is guaranteed to be non-zero - unsafe { NonNull::new_unchecked(crate::ptr::without_provenance_mut::(self.align())) } + NonNull::without_provenance(self.align.as_nonzero()) } /// Creates a layout describing the record that can hold a value diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index f958a938646..716da37168d 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -103,7 +103,8 @@ //! the time. use core::marker::PhantomData; -use core::ptr::{self, NonNull}; +use core::num::NonZeroUsize; +use core::ptr::NonNull; use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage}; @@ -176,7 +177,7 @@ impl Repr { let utagged = ((code as usize) << 32) | TAG_OS; // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. let res = Self( - unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) }, + NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }), PhantomData, ); // quickly smoke-check we encoded the right thing (This generally will @@ -193,7 +194,7 @@ impl Repr { let utagged = ((kind as usize) << 32) | TAG_SIMPLE; // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0. let res = Self( - unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) }, + NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }), PhantomData, ); // quickly smoke-check we encoded the right thing (This generally will diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2f8f5c5c581..4b80b3d0e67 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -342,6 +342,7 @@ #![feature(lazy_get)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] +#![feature(nonnull_provenance)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] -- cgit 1.4.1-3-g733a5 From df57d65c708354d2e2549217a5fa4d7ca89eebfc Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Sat, 11 Jan 2025 22:18:52 +0100 Subject: Make UniqueRc invariant for soundness --- library/alloc/src/rc.rs | 8 ++++++-- tests/ui/variance/variance-uniquerc.rs | 27 +++++++++++++++++++++++++++ tests/ui/variance/variance-uniquerc.stderr | 15 +++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/ui/variance/variance-uniquerc.rs create mode 100644 tests/ui/variance/variance-uniquerc.stderr (limited to 'library/alloc/src') diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 9256cb0703a..ae3318b839d 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3708,7 +3708,11 @@ pub struct UniqueRc< #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { ptr: NonNull>, - phantom: PhantomData>, + // Define the ownership of `RcInner` for drop-check + _marker: PhantomData>, + // Invariance is necessary for soundness: once other `Weak` + // references exist, we already have a form of shared mutability! + _marker2: PhantomData<*mut T>, alloc: A, } @@ -3994,7 +3998,7 @@ impl UniqueRc { }, alloc, )); - Self { ptr: ptr.into(), phantom: PhantomData, alloc } + Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc } } } diff --git a/tests/ui/variance/variance-uniquerc.rs b/tests/ui/variance/variance-uniquerc.rs new file mode 100644 index 00000000000..0c395ab06ea --- /dev/null +++ b/tests/ui/variance/variance-uniquerc.rs @@ -0,0 +1,27 @@ +// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164 +// we should also test UniqueArc once implemented +// +// inline comments explain how this code *would* compile if UniqueRc was still covariant + +#![feature(unique_rc_arc)] + +use std::rc::UniqueRc; + +fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str { + let r = UniqueRc::new(""); // UniqueRc<&'static str> + let w = UniqueRc::downgrade(&r); // Weak<&'static str> + let mut r = r; // [IF COVARIANT]: ==>> UniqueRc<&'a str> + *r = x; // assign the &'a str + let _r = UniqueRc::into_rc(r); // Rc<&'a str>, but we only care to activate the weak + let r = w.upgrade().unwrap(); // Rc<&'static str> + *r // &'static str, coerces to &'b str + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let s = String::from("Hello World!"); + let r = extend_lifetime(&s); + println!("{r}"); + drop(s); + println!("{r}"); +} diff --git a/tests/ui/variance/variance-uniquerc.stderr b/tests/ui/variance/variance-uniquerc.stderr new file mode 100644 index 00000000000..1557f7e40c5 --- /dev/null +++ b/tests/ui/variance/variance-uniquerc.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/variance-uniquerc.rs:17:5 + | +LL | fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | *r // &'static str, coerces to &'b str + | ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 1 previous error + -- cgit 1.4.1-3-g733a5 From e37daf0c868efc016dd8039d59d53a03303c9c07 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sun, 18 Aug 2024 19:50:41 -0400 Subject: Add inherent versions of MaybeUninit methods for slices --- compiler/rustc_arena/src/lib.rs | 2 +- library/alloc/src/collections/btree/node.rs | 4 +- library/core/src/array/iter.rs | 8 +- library/core/src/array/mod.rs | 4 +- library/core/src/io/borrowed_buf.rs | 14 +- library/core/src/iter/adapters/filter_map.rs | 4 +- library/core/src/mem/maybe_uninit.rs | 564 ++++++++++++++---------- library/core/src/net/display_buffer.rs | 4 +- library/core/src/num/flt2dec/mod.rs | 48 +- library/core/src/num/flt2dec/strategy/dragon.rs | 10 +- library/core/src/num/flt2dec/strategy/grisu.rs | 10 +- library/core/tests/mem.rs | 32 +- library/proc_macro/src/bridge/arena.rs | 2 +- library/std/src/ffi/os_str/tests.rs | 2 +- library/std/src/io/buffered/bufreader/buffer.rs | 2 +- library/std/src/path/tests.rs | 4 +- library/std/src/sys/pal/windows/mod.rs | 2 +- library/std/src/sys/pal/windows/stdio.rs | 6 +- 18 files changed, 412 insertions(+), 310 deletions(-) (limited to 'library/alloc/src') diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 4d8525989cc..b21ccba93bb 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -78,7 +78,7 @@ impl ArenaChunk { // been initialized. unsafe { let slice = self.storage.as_mut(); - ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len])); + slice[..len].assume_init_drop(); } } } diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 0c93eff0d20..4057657632b 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -383,9 +383,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// Borrows a view into the keys stored in the node. pub fn keys(&self) -> &[K] { let leaf = self.into_leaf(); - unsafe { - MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len))) - } + unsafe { leaf.keys.get_unchecked(..usize::from(leaf.len)).assume_init_ref() } } } 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 IntoIter { // 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 IntoIter { // 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 Iterator for IntoIter { // 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 DoubleEndedIterator for IntoIter { // 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 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/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::() } { // 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/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 284a58c7278..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 MaybeUninit { /// fn read(buf: &mut [MaybeUninit]) -> &[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() /// } /// } /// @@ -740,7 +740,7 @@ impl MaybeUninit { /// /// 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`] to an invalid but + /// rely on this. For example, setting a `Vec` 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 MaybeUninit { /// behavior. /// /// [`assume_init`]: MaybeUninit::assume_init - /// [`Vec`]: ../../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 MaybeUninit { } } - /// 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` 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] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts(self.as_ptr().cast::>(), super::size_of::()) + } } - /// 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` 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] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().cast::>(), + super::size_of::(), + ) + } + } + + /// 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 MaybeUninit { 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], src: &[T]) -> &'a mut [T] where T: Copy, { - // SAFETY: &[T] and &[MaybeUninit] have the same layout - let uninit_src: &[MaybeUninit] = 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], 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` 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 MaybeUninit { /// /// # 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], value: T) -> &'a mut [T] + pub fn fill(this: &mut [MaybeUninit], 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 MaybeUninit { /// /// # Examples /// - /// Fill an uninit vec with the default value. /// ``` /// #![feature(maybe_uninit_fill)] /// use std::mem::MaybeUninit; /// - /// let mut buf = vec![MaybeUninit::::uninit(); 10]; - /// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default); + /// let mut buf = [const { MaybeUninit::::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], mut f: F) -> &'a mut [T] + pub fn fill_with(this: &mut [MaybeUninit], mut f: F) -> &mut [T] where F: FnMut() -> T, { @@ -1244,13 +1176,13 @@ impl MaybeUninit { 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 MaybeUninit { /// /// # 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], - it: I, - ) -> (&'a mut [T], &'a mut [MaybeUninit]) + pub fn fill_from(this: &mut [MaybeUninit], it: I) -> (&mut [T], &mut [MaybeUninit]) where I: IntoIterator, { @@ -1312,70 +1258,169 @@ impl MaybeUninit { // 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]) -> &[MaybeUninit] { + 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]) -> &mut [MaybeUninit] { + this.as_bytes_mut() + } +} + +impl [MaybeUninit] { + /// 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] { - // SAFETY: MaybeUninit is always valid, even for padding bytes - unsafe { - slice::from_raw_parts(self.as_ptr() as *const MaybeUninit, mem::size_of::()) - } + /// + /// ``` + /// #![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] have the same layout + let uninit_src: &[MaybeUninit] = 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] { - // SAFETY: MaybeUninit is always valid, even for padding bytes - unsafe { - slice::from_raw_parts_mut( - self.as_mut_ptr() as *mut MaybeUninit, - mem::size_of::(), - ) + /// + /// [`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` 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 MaybeUninit { /// 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]) -> &[MaybeUninit] { - let bytes = mem::size_of_val(this); + pub const fn as_bytes(&self) -> &[MaybeUninit] { // SAFETY: MaybeUninit is always valid, even for padding bytes - unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit, bytes) } + unsafe { + slice::from_raw_parts(self.as_ptr().cast::>(), 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 MaybeUninit { /// /// let mut uninit = [MaybeUninit::::uninit(), MaybeUninit::::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 MaybeUninit { /// } /// ``` #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] - pub fn slice_as_bytes_mut(this: &mut [MaybeUninit]) -> &mut [MaybeUninit] { - let bytes = mem::size_of_val(this); + pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit] { // SAFETY: MaybeUninit is always valid, even for padding bytes - unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit, bytes) } + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr() as *mut MaybeUninit, + super::size_of_val(self), + ) + } + } + + /// Drops the contained values in place. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that every `MaybeUninit` 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` 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` 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] 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` 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` 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/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 DisplayBuffer { // 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 fmt::Write for DisplayBuffer { 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/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/tests/mem.rs b/library/core/tests/mem.rs index f3b4387f6a8..1b5c5fc82a6 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -200,60 +200,60 @@ fn uninit_array_assume_init() { } #[test] -fn uninit_write_slice() { +fn uninit_write_copy_of_slice() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 64]; - assert_eq!(MaybeUninit::copy_from_slice(&mut dst, &src), &src); + assert_eq!(dst.write_copy_of_slice(&src), &src); } #[test] #[should_panic(expected = "source slice length (32) does not match destination slice length (64)")] -fn uninit_write_slice_panic_lt() { +fn uninit_write_copy_of_slice_panic_lt() { let mut dst = [MaybeUninit::uninit(); 64]; let src = [0; 32]; - MaybeUninit::copy_from_slice(&mut dst, &src); + dst.write_copy_of_slice(&src); } #[test] #[should_panic(expected = "source slice length (128) does not match destination slice length (64)")] -fn uninit_write_slice_panic_gt() { +fn uninit_write_copy_of_slice_panic_gt() { let mut dst = [MaybeUninit::uninit(); 64]; let src = [0; 128]; - MaybeUninit::copy_from_slice(&mut dst, &src); + dst.write_copy_of_slice(&src); } #[test] -fn uninit_clone_from_slice() { +fn uninit_write_clone_of_slice() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 64]; - assert_eq!(MaybeUninit::clone_from_slice(&mut dst, &src), &src); + assert_eq!(dst.write_clone_of_slice(&src), &src); } #[test] #[should_panic(expected = "destination and source slices have different lengths")] -fn uninit_write_slice_cloned_panic_lt() { +fn uninit_write_clone_of_slice_panic_lt() { let mut dst = [MaybeUninit::uninit(); 64]; let src = [0; 32]; - MaybeUninit::clone_from_slice(&mut dst, &src); + dst.write_clone_of_slice(&src); } #[test] #[should_panic(expected = "destination and source slices have different lengths")] -fn uninit_write_slice_cloned_panic_gt() { +fn uninit_write_clone_of_slice_panic_gt() { let mut dst = [MaybeUninit::uninit(); 64]; let src = [0; 128]; - MaybeUninit::clone_from_slice(&mut dst, &src); + dst.write_clone_of_slice(&src); } #[test] #[cfg(panic = "unwind")] -fn uninit_write_slice_cloned_mid_panic() { +fn uninit_write_clone_of_slice_mid_panic() { use std::panic; enum IncrementOrPanic { @@ -289,7 +289,7 @@ fn uninit_write_slice_cloned_mid_panic() { ]; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::clone_from_slice(&mut dst, &src); + dst.write_clone_of_slice(&src); })); drop(src); @@ -317,11 +317,11 @@ impl Drop for Bomb { } #[test] -fn uninit_write_slice_cloned_no_drop() { +fn uninit_write_clone_of_slice_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = [Bomb]; - MaybeUninit::clone_from_slice(&mut dst, &src); + dst.write_clone_of_slice(&src); forget(src); } diff --git a/library/proc_macro/src/bridge/arena.rs b/library/proc_macro/src/bridge/arena.rs index 1d5986093c8..29636e793f6 100644 --- a/library/proc_macro/src/bridge/arena.rs +++ b/library/proc_macro/src/bridge/arena.rs @@ -102,7 +102,7 @@ impl Arena { #[allow(clippy::mut_from_ref)] // arena allocator pub(crate) fn alloc_str<'a>(&'a self, string: &str) -> &'a mut str { let alloc = self.alloc_raw(string.len()); - let bytes = MaybeUninit::copy_from_slice(alloc, string.as_bytes()); + let bytes = alloc.write_copy_of_slice(string.as_bytes()); // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena, // and immediately convert the clone back to `&str`. diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs index cbec44c8626..2572b71fd9a 100644 --- a/library/std/src/ffi/os_str/tests.rs +++ b/library/std/src/ffi/os_str/tests.rs @@ -295,7 +295,7 @@ fn clone_to_uninit() { let mut storage = vec![MaybeUninit::::uninit(); size_of_val::(a)]; unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) }; - assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) }); + assert_eq!(a.as_encoded_bytes(), unsafe { storage.assume_init_ref() }); let mut b: Box = OsStr::new("world.exe").into(); assert_eq!(size_of_val::(a), size_of_val::(&b)); diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 17721090db5..5251cc302cb 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -50,7 +50,7 @@ impl Buffer { pub fn buffer(&self) -> &[u8] { // SAFETY: self.pos and self.cap are valid, and self.cap => self.pos, and // that region is initialized because those are all invariants of this type. - unsafe { MaybeUninit::slice_assume_init_ref(self.buf.get_unchecked(self.pos..self.filled)) } + unsafe { self.buf.get_unchecked(self.pos..self.filled).assume_init_ref() } } #[inline] diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index ff3f7151bb8..3f96ac4672a 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -2069,9 +2069,7 @@ fn clone_to_uninit() { let mut storage = vec![MaybeUninit::::uninit(); size_of_val::(a)]; unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) }; - assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe { - MaybeUninit::slice_assume_init_ref(&storage) - }); + assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe { storage.assume_init_ref() }); let mut b: Box = Path::new("world.exe").into(); assert_eq!(size_of_val::(a), size_of_val::(&b)); diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 88e6def7a75..4282dbb5493 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -272,7 +272,7 @@ where unreachable!(); } else { // Safety: First `k` values are initialized. - let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]); + let slice: &[u16] = buf[..k].assume_init_ref(); return Ok(f2(slice)); } } diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs index 1b735e7f0cb..fd3f559ba19 100644 --- a/library/std/src/sys/pal/windows/stdio.rs +++ b/library/std/src/sys/pal/windows/stdio.rs @@ -207,7 +207,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result return Ok(bytes_copied + value), Err(e) => return Err(e), -- cgit 1.4.1-3-g733a5