From b0b7c9a2fb7cf7cbce21673ab1d41dbf1821fc22 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Wed, 4 Feb 2026 15:54:49 +0000 Subject: [PATCH] [wip] Introduce `Ptr::project_map` Enables piecewise initialization. gherrit-pr-id: Gc3e9ee9afa6945e10c35be84d30c970894395c96 --- src/impls.rs | 22 +++++++++++++++------- src/lib.rs | 5 +++++ src/pointer/invariant.rs | 10 ++++++++++ src/pointer/ptr.rs | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/impls.rs b/src/impls.rs index d1344098cf..46c66f7e73 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -1080,16 +1080,24 @@ mod tuples { // The types and indices at and after the current index. [$CurrT:ident $CurrV:ident $CurrI:tt $($AfterT:ident $AfterV:ident $AfterI:tt)*] ) => { + impl crate::invariant::Map> for ($($AllT,)+) + where + Replacement: crate::invariant::Validity, + $($AllT: crate::invariant::Validity,)* + { + type Result = ($($BeforeT,)* Replacement, $($AfterT,)*); + } + // SAFETY: // - `Self` is a struct (albeit anonymous), so `VARIANT_ID` is // `STRUCT_VARIANT_ID`. // - `$CurrI` is the field at index `$CurrI`, so `FIELD_ID` is // `zerocopy::ident_id!($CurrI)` - // - `()` has the same visibility as the `.$CurrI` field (ie, `.0`, - // `.1`, etc) + // - `crate::Idx` has the same visibility as the `.$CurrI` field + // (ie, `.0`, `.1`, etc) // - `Type` has the same type as `$CurrI`; i.e., `$CurrT`. unsafe impl<$($AllT),+> crate::HasField< - (), + crate::Idx<{ $CurrI }>, { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($CurrI)} > for ($($AllT,)+) { @@ -1115,7 +1123,7 @@ mod tuples { // SAFETY: See comments on items. unsafe impl crate::ProjectField< - (), + crate::Idx<{ $CurrI }>, (Aliasing, Alignment, crate::invariant::Uninit), { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($CurrI)} @@ -1141,7 +1149,7 @@ mod tuples { // SAFETY: See comments on items. unsafe impl crate::ProjectField< - (), + crate::Idx<{ $CurrI }>, (Aliasing, Alignment, crate::invariant::Initialized), { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($CurrI)} @@ -1167,7 +1175,7 @@ mod tuples { // SAFETY: See comments on items. unsafe impl crate::ProjectField< - (), + crate::Idx<{ $CurrI }>, (Aliasing, Alignment, crate::invariant::Valid), { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($CurrI)} @@ -1193,7 +1201,7 @@ mod tuples { // SAFETY: See comments on items. unsafe impl crate::ProjectField< - (), + crate::Idx<{ $CurrI }>, (Aliasing, Alignment, ($($AllV,)+)), { crate::STRUCT_VARIANT_ID }, { crate::ident_id!($CurrI)} diff --git a/src/lib.rs b/src/lib.rs index 23793e3882..0603659c5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1123,6 +1123,11 @@ pub const UNION_VARIANT_ID: i128 = -2; #[doc(hidden)] pub const REPR_C_UNION_VARIANT_ID: i128 = -3; +/// A field visibility token for public tuple fields. +#[allow(missing_copy_implementations, missing_debug_implementations)] +#[doc(hidden)] +pub struct Idx; + /// # Safety /// /// `Self::ProjectToTag` must satisfy its safety invariant. diff --git a/src/pointer/invariant.rs b/src/pointer/invariant.rs index 0ce795f260..cff8a98c23 100644 --- a/src/pointer/invariant.rs +++ b/src/pointer/invariant.rs @@ -277,6 +277,16 @@ pub enum BecauseExclusive {} #[doc(hidden)] pub enum BecauseImmutable {} +/// Replaces a validity component. +/// +/// The [`Self::Result`] is a validity identical `Self` except that the +/// component corresponding to `Field` component has been replaced with +/// `Replacement`. +#[doc(hidden)] +pub trait Map { + type Result: Validity; +} + use sealed::Sealed; pub(crate) mod sealed { use super::*; diff --git a/src/pointer/ptr.rs b/src/pointer/ptr.rs index 83c116747b..5e3781567e 100644 --- a/src/pointer/ptr.rs +++ b/src/pointer/ptr.rs @@ -914,6 +914,38 @@ mod _casts { tag.unify_invariants() } + #[inline(always)] + pub fn project_map( + mut self, + map: impl for<'b> FnOnce( + Ptr<'b, T::Type, T::Invariants>, + ) -> Ptr< + 'b, + T::Type, + ( + ::Aliasing, + ::Alignment, + V, + ), + >, + ) -> Result< + Ptr<'a, T, (I::Aliasing, I::Alignment, >::Result)>, + T::Error, + > + where + T: ProjectField, + I::Aliasing: Reference, + I::Validity: Map, + V: Validity, + { + let _mapped = match self.reborrow().project() { + Ok(field) => map(field), + Err(err) => return Err(err), + }; + // SAFETY: TODO + Ok(unsafe { self.assume_validity() }) + } + /// Attempts to transform the pointer, restoring the original on /// failure. ///