From 95c531a59aac437d7b486a2ca732c1559f4cf9c5 Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Sat, 14 Jun 2025 20:25:07 +0000 Subject: [PATCH 1/4] [lib] in-place initialization infrastructure This is the initial design of the in-place initialization interface, without the `PinInit` part. Signed-off-by: Xiangfei Ding Co-authored-by: Benno Lossin Co-authored-by: Alice Ryhl --- compiler/rustc_hir/src/lang_items.rs | 5 +++ compiler/rustc_span/src/symbol.rs | 5 +++ library/core/src/init.rs | 52 ++++++++++++++++++++++++++++ library/core/src/lib.rs | 4 +++ 4 files changed, 66 insertions(+) create mode 100644 library/core/src/init.rs diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 21d36ed54cdf4..5c6aff3d86439 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -350,6 +350,11 @@ language_item_table! { MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None; + Init, sym::init_trait, init_trait, Target::Trait, GenericRequirement::Exact(1); + InitError, sym::init_error, init_error, Target::AssocTy, GenericRequirement::Exact(1); + InitLayout, sym::init_layout, init_layout, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1); + InitInit, sym::init_init, init_init, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(1); + Termination, sym::termination, termination, Target::Trait, GenericRequirement::None; Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cb9ccf4cc3f23..53eac7081826c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1200,6 +1200,11 @@ symbols! { infer_static_outlives_requirements, inherent_associated_types, inherit, + init, + init_error, + init_init, + init_layout, + init_trait, inlateout, inline, inline_const, diff --git a/library/core/src/init.rs b/library/core/src/init.rs new file mode 100644 index 0000000000000..cfb012b8f71b0 --- /dev/null +++ b/library/core/src/init.rs @@ -0,0 +1,52 @@ +//! In-place initialization +//! +//! This module describes the interface through which types supporting in-place initialization +//! interact with allocation mechanism to ensure correct and safe initialization of values +//! within the memory slots provided by the allocation. + +use crate::ptr::Pointee; + +/// # Safety +/// +/// Implementers must ensure that if `init` returns `Ok(metadata)`, then +/// `core::ptr::from_raw_parts_mut(slot, metadata)` must reference a valid +/// value owned by the caller. Furthermore, the layout returned by using +/// `size_of` and `align_of` on this pointer must match what `Self::layout()` +/// returns exactly. +/// +/// Implementers must ensure that the implementation of `init()` does not rely +/// on the value being pinned. +#[unstable(feature = "in_place_initialization", issue = "999999")] +#[lang = "init_trait"] +pub unsafe trait Init { + /// Error type upon initialization failure during the actual + /// in-place initialization procedure. + #[lang = "init_error"] + type Error; + + /// The layout needed by this initializer, which the allocation + /// should arrange the destination memory slot accordingly. + #[lang = "init_layout"] + fn layout(&self) -> crate::alloc::Layout; + + /// Writes a valid value of type `T` to `slot` or fails. + /// + /// If this call returns [`Ok`], then `slot` is guaranteed to contain a valid + /// value of type `T`. If `T` is unsized, then `slot` may be combined with + /// the metadata to obtain a valid pointer to the value. + /// + /// Note that `slot` should be thought of as a `*mut T`. A unit type is used + /// so that the pointer is thin even if `T` is unsized. + /// + /// # Safety + /// + /// The caller must provide a pointer that references a location that `init` + /// may write to, and the location must have at least the size and alignment + /// specified by [`Init::layout`]. + /// + /// If this call returns `Ok` and the initializer does not implement + /// `Init`, then `slot` contains a pinned value, and the caller must + /// respect the usual pinning requirements for `slot`. + #[lang = "init_init"] + unsafe fn init(self, slot: *mut ()) -> Result; +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 88855831788db..e4c092ffc98a9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -363,6 +363,10 @@ pub mod task; #[allow(missing_docs)] pub mod alloc; +/* In-place initialization */ +#[unstable(feature = "in_place_initialization", issue = "999999")] +pub mod init; + // note: does not need to be public mod bool; mod escape; From 99131767f4dd7b59415abd1c287993441a41b801 Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Tue, 17 Jun 2025 13:53:40 +0000 Subject: [PATCH 2/4] apply suggestions Signed-off-by: Xiangfei Ding --- library/core/src/init.rs | 62 +++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/library/core/src/init.rs b/library/core/src/init.rs index cfb012b8f71b0..64b0a508f8b11 100644 --- a/library/core/src/init.rs +++ b/library/core/src/init.rs @@ -1,21 +1,60 @@ -//! In-place initialization +//! In-place initialization. //! //! This module describes the interface through which types supporting in-place initialization -//! interact with allocation mechanism to ensure correct and safe initialization of values -//! within the memory slots provided by the allocation. +//! can perform initialization with minimal or zero additional allocations or moves. use crate::ptr::Pointee; +/// In-place Initializer for `T`. +/// +/// An instance of `Init` carries all the information necessary to initialize a `T` in a +/// well-defined memory location, criteria of which is prescribed in the Safety section. +/// +/// # Fallibility +/// +/// The initialization might fail and return an error of type [`Self::Error`] instead. +/// In that case, the memory provided to [`Self::init`] shall be repurposed in any way, +/// even though it might have been written to by this initializer. +/// +/// # Examples +/// +/// ## Initializing unsized types +/// +/// To initialize an unsized type, first query the required layout for `T` using [`Self::layout`]. +/// Then provide a pointer to an allocation of at least the specified alignment and size. +/// +/// If initialization was successful, then [`Self::init`] returns the metadata that combined with +/// the pointer to the given to [`Self::init`] yields a valid pointer to `T`. +/// +/// ``` +/// use std::alloc::alloc; +/// fn init_unsized>(init: I) -> Result, I::Error> { +/// let layout = init.layout(); +/// let memory = alloc(layout).cast::<()>(); +/// let meta = init.init(memory)?; +/// Box::from_raw(from_raw_parts_mut(memory, meta)) +/// } +/// ``` +/// /// # Safety /// -/// Implementers must ensure that if `init` returns `Ok(metadata)`, then -/// `core::ptr::from_raw_parts_mut(slot, metadata)` must reference a valid -/// value owned by the caller. Furthermore, the layout returned by using -/// `size_of` and `align_of` on this pointer must match what `Self::layout()` -/// returns exactly. +/// Implementers must ensure that if [`self.init(slot)`] returns `Ok(metadata)`, +/// then [`core::ptr::from_raw_parts_mut(slot, metadata)`] must reference a valid +/// value owned by the caller. +/// Furthermore, the layout returned by using +/// [`core::intrinsics::size_of_val`] and [`core::intrinsics::align_of_val`] on this pointer +/// must match what [`Self::layout()`] returns exactly. +/// +/// If `T` is sized, or in other words `T: Sized`, [`Init::layout`] in this case *must* +/// return the same layout as [`Layout::new::()`] would. /// /// Implementers must ensure that the implementation of `init()` does not rely /// on the value being pinned. +/// +/// [`core::ptr::from_raw_parts_mut(slot, metadata)`]: core::ptr::from_raw_parts_mut +/// [`Self::layout()`]: Init::layout +/// [`self.init(slot)`]: Init::init +/// [`Layout::new::()`]: core::alloc::Layout::new #[unstable(feature = "in_place_initialization", issue = "999999")] #[lang = "init_trait"] pub unsafe trait Init { @@ -24,8 +63,7 @@ pub unsafe trait Init { #[lang = "init_error"] type Error; - /// The layout needed by this initializer, which the allocation - /// should arrange the destination memory slot accordingly. + /// The layout needed by this initializer. #[lang = "init_layout"] fn layout(&self) -> crate::alloc::Layout; @@ -43,10 +81,6 @@ pub unsafe trait Init { /// The caller must provide a pointer that references a location that `init` /// may write to, and the location must have at least the size and alignment /// specified by [`Init::layout`]. - /// - /// If this call returns `Ok` and the initializer does not implement - /// `Init`, then `slot` contains a pinned value, and the caller must - /// respect the usual pinning requirements for `slot`. #[lang = "init_init"] unsafe fn init(self, slot: *mut ()) -> Result; } From ca9f572e1a00cf309216a7e83c95ebe2920e258b Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Fri, 20 Jun 2025 07:29:06 +0000 Subject: [PATCH 3/4] apply suggestions --- library/core/src/init.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/init.rs b/library/core/src/init.rs index 64b0a508f8b11..76d0b81a98988 100644 --- a/library/core/src/init.rs +++ b/library/core/src/init.rs @@ -26,9 +26,9 @@ use crate::ptr::Pointee; /// If initialization was successful, then [`Self::init`] returns the metadata that combined with /// the pointer to the given to [`Self::init`] yields a valid pointer to `T`. /// -/// ``` +/// ``` ignore (illustrative) /// use std::alloc::alloc; -/// fn init_unsized>(init: I) -> Result, I::Error> { +/// fn init_boxed>(init: I) -> Result, I::Error> { /// let layout = init.layout(); /// let memory = alloc(layout).cast::<()>(); /// let meta = init.init(memory)?; @@ -64,6 +64,9 @@ pub unsafe trait Init { type Error; /// The layout needed by this initializer. + /// This method must return a layout that precisely matches + /// with `T`. + /// Namely the size and the alignment must be equal. #[lang = "init_layout"] fn layout(&self) -> crate::alloc::Layout; From 765a241ff955bea3677cdb1178d82362baf54f7e Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Fri, 20 Jun 2025 20:49:25 +0000 Subject: [PATCH 4/4] add missing documentation on `Err` case Signed-off-by: Xiangfei Ding --- library/core/src/init.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/core/src/init.rs b/library/core/src/init.rs index 76d0b81a98988..0ac0b5d75eb77 100644 --- a/library/core/src/init.rs +++ b/library/core/src/init.rs @@ -73,7 +73,11 @@ pub unsafe trait Init { /// Writes a valid value of type `T` to `slot` or fails. /// /// If this call returns [`Ok`], then `slot` is guaranteed to contain a valid - /// value of type `T`. If `T` is unsized, then `slot` may be combined with + /// value of type `T`. + /// Otherwise, in case the result is an [`Err`], the implementation must guarantee + /// that the `slot` may be repurposed for future reuse. + /// + /// If `T` is unsized, then `slot` may be combined with /// the metadata to obtain a valid pointer to the value. /// /// Note that `slot` should be thought of as a `*mut T`. A unit type is used