Simplify the type bounds on PrimitiveMut via type erasure

PiperOrigin-RevId: 591046477
diff --git a/rust/primitive.rs b/rust/primitive.rs
index 539ddf2..ea74218 100644
--- a/rust/primitive.rs
+++ b/rust/primitive.rs
@@ -15,17 +15,20 @@
 /// A mutator for a primitive (numeric or enum) value of `T`.
 ///
 /// This type is `protobuf::Mut<'msg, T>`.
-pub struct PrimitiveMut<'msg, T: ProxiedWithRawVTable> {
+pub struct PrimitiveMut<'msg, T> {
     inner: InnerPrimitiveMut<'msg, T>,
 }
 
-impl<'msg, T: ProxiedWithRawVTable> Debug for PrimitiveMut<'msg, T> {
+impl<'msg, T> Debug for PrimitiveMut<'msg, T>
+where
+    T: PrimitiveWithRawVTable,
+{
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("PrimitiveMut").field("inner", &self.inner).finish()
     }
 }
 
-impl<'msg, T: ProxiedWithRawVTable> PrimitiveMut<'msg, T> {
+impl<'msg, T> PrimitiveMut<'msg, T> {
     /// # Safety
     /// `inner` must be valid and non-aliased for `T` for `'msg`
     #[doc(hidden)]
@@ -34,7 +37,7 @@
     }
 }
 
-unsafe impl<'msg, T: ProxiedWithRawVTable> Sync for PrimitiveMut<'msg, T> {}
+unsafe impl<'msg, T> Sync for PrimitiveMut<'msg, T> {}
 
 impl<'msg, T> PrimitiveMut<'msg, T>
 where
diff --git a/rust/vtable.rs b/rust/vtable.rs
index f0128db..2691125 100644
--- a/rust/vtable.rs
+++ b/rust/vtable.rs
@@ -14,6 +14,8 @@
     ProxiedWithPresence, View, ViewProxy,
 };
 use std::fmt::{self, Debug};
+use std::marker::PhantomData;
+use std::ptr::NonNull;
 
 /// A proxied type that can use a vtable to provide get/set access for a
 /// present field.
@@ -67,7 +69,8 @@
             AbsentMutData<'msg> = RawVTableOptionalMutatorData<'msg, T>,
         >,
 {
-    let data = RawVTableOptionalMutatorData { msg_ref, vtable: optional_vtable };
+    // SAFETY: safe as promised by the caller of the function
+    let data = unsafe { RawVTableOptionalMutatorData::new(Private, msg_ref, optional_vtable) };
     if is_set {
         Optional::Set(PresentField::from_inner(Private, data))
     } else {
@@ -89,26 +92,29 @@
 ///
 /// [`RawVTableOptionalMutatorData`] is similar, but also includes the
 /// capability to has/clear.
-pub struct RawVTableMutator<'msg, T: ProxiedWithRawVTable + ?Sized> {
+pub struct RawVTableMutator<'msg, T: ?Sized> {
     msg_ref: MutatorMessageRef<'msg>,
-    vtable: &'static T::VTable,
+    /// Stores `&'static <T as ProxiedWithRawVTable>::Vtable`
+    /// as a type-erased pointer to avoid a bound on the struct.
+    vtable: NonNull<()>,
+    _phantom: PhantomData<&'msg T>,
 }
 
 // These use manual impls instead of derives to avoid unnecessary bounds on `T`.
 // This problem is referred to as "perfect derive".
 // https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/
-impl<'msg, T: ProxiedWithRawVTable + ?Sized> Clone for RawVTableMutator<'msg, T> {
+impl<'msg, T: ?Sized> Clone for RawVTableMutator<'msg, T> {
     fn clone(&self) -> Self {
         *self
     }
 }
-impl<'msg, T: ProxiedWithRawVTable + ?Sized> Copy for RawVTableMutator<'msg, T> {}
+impl<'msg, T: ?Sized> Copy for RawVTableMutator<'msg, T> {}
 
 impl<'msg, T: ProxiedWithRawVTable + ?Sized> Debug for RawVTableMutator<'msg, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RawVTableMutator")
             .field("msg_ref", &self.msg_ref)
-            .field("vtable", &self.vtable)
+            .field("vtable", self.vtable())
             .finish()
     }
 }
@@ -125,7 +131,12 @@
         msg_ref: MutatorMessageRef<'msg>,
         vtable: &'static T::VTable,
     ) -> Self {
-        RawVTableMutator { msg_ref, vtable }
+        RawVTableMutator { msg_ref, vtable: NonNull::from(vtable).cast(), _phantom: PhantomData }
+    }
+
+    fn vtable(self) -> &'static T::VTable {
+        // SAFETY: This was cast from `&'static T::VTable`.
+        unsafe { self.vtable.cast().as_ref() }
     }
 }
 
@@ -138,30 +149,27 @@
 ///
 /// This has the same representation for "present" and "absent" data;
 /// differences like default values are obviated by the vtable.
-pub struct RawVTableOptionalMutatorData<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> {
+pub struct RawVTableOptionalMutatorData<'msg, T: ?Sized> {
     msg_ref: MutatorMessageRef<'msg>,
-    vtable: &'static T::OptionalVTable,
+    /// Stores `&'static <T as ProxiedWithRawOptionalVTable>::Vtable`
+    /// as a type-erased pointer to avoid a bound on the struct.
+    optional_vtable: NonNull<()>,
+    _phantom: PhantomData<&'msg T>,
 }
 
-unsafe impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Sync
-    for RawVTableOptionalMutatorData<'msg, T>
-{
-}
+// SAFETY: all `T` that can perform mutations don't mutate through a shared
+// reference.
+unsafe impl<'msg, T: ?Sized> Sync for RawVTableOptionalMutatorData<'msg, T> {}
 
 // These use manual impls instead of derives to avoid unnecessary bounds on `T`.
 // This problem is referred to as "perfect derive".
 // https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/
-impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Clone
-    for RawVTableOptionalMutatorData<'msg, T>
-{
+impl<'msg, T: ?Sized> Clone for RawVTableOptionalMutatorData<'msg, T> {
     fn clone(&self) -> Self {
         *self
     }
 }
-impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Copy
-    for RawVTableOptionalMutatorData<'msg, T>
-{
-}
+impl<'msg, T: ?Sized> Copy for RawVTableOptionalMutatorData<'msg, T> {}
 
 impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Debug
     for RawVTableOptionalMutatorData<'msg, T>
@@ -169,7 +177,7 @@
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RawVTableOptionalMutatorData")
             .field("msg_ref", &self.msg_ref)
-            .field("vtable", &self.vtable)
+            .field("vtable", self.optional_vtable())
             .finish()
     }
 }
@@ -186,11 +194,23 @@
         msg_ref: MutatorMessageRef<'msg>,
         vtable: &'static T::OptionalVTable,
     ) -> Self {
-        Self { msg_ref, vtable }
+        Self { msg_ref, optional_vtable: NonNull::from(vtable).cast(), _phantom: PhantomData }
+    }
+
+    fn optional_vtable(self) -> &'static T::OptionalVTable {
+        // SAFETY: This was cast from `&'static T::OptionalVTable` in `new`.
+        unsafe { self.optional_vtable.cast().as_ref() }
     }
 
     fn into_raw_mut(self) -> RawVTableMutator<'msg, T> {
-        RawVTableMutator { msg_ref: self.msg_ref, vtable: T::upcast_vtable(Private, self.vtable) }
+        // SAFETY: the safety requirements have been met by the caller of `new`.
+        unsafe {
+            RawVTableMutator::new(
+                Private,
+                self.msg_ref,
+                T::upcast_vtable(Private, self.optional_vtable()),
+            )
+        }
     }
 }
 
@@ -342,7 +362,7 @@
         // - `msg_ref` is valid for `'msg` as promised by the caller of `new`.
         // - The caller of `BytesMutVTable` promised that the returned `PtrAndLen` is
         //   valid for `'msg`.
-        unsafe { (self.vtable.getter)(self.msg_ref.msg()).as_ref() }
+        unsafe { (self.vtable().getter)(self.msg_ref.msg()).as_ref() }
     }
 
     /// # Safety
@@ -353,7 +373,7 @@
         let val = copy_bytes_in_arena_if_needed_by_runtime(self.msg_ref, val);
         // SAFETY:
         // - `msg_ref` is valid for `'msg` as promised by the caller of `new`.
-        unsafe { (self.vtable.setter)(self.msg_ref.msg(), val.into()) }
+        unsafe { (self.vtable().setter)(self.msg_ref.msg(), val.into()) }
     }
 
     pub(crate) fn truncate(&self, len: usize) {
@@ -373,7 +393,7 @@
     pub(crate) fn set_absent_to_default(self) -> Self {
         // SAFETY: The default value is UTF-8 if required by the
         // runtime as promised by the caller of `BytesOptionalMutVTable::new`.
-        unsafe { self.set(self.vtable.default) }
+        unsafe { self.set(self.optional_vtable().default) }
     }
 
     /// # Safety
@@ -383,7 +403,7 @@
         let val = copy_bytes_in_arena_if_needed_by_runtime(self.msg_ref, val);
         // SAFETY:
         // - `msg_ref` is valid for `'msg` as promised by the caller.
-        unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val.into()) }
+        unsafe { (self.optional_vtable().base.setter)(self.msg_ref.msg(), val.into()) }
         self
     }
 
@@ -392,7 +412,7 @@
         // - `msg_ref` is valid for `'msg` as promised by the caller.
         // - The caller of `new` promised that the returned `PtrAndLen` is valid for
         //   `'msg`.
-        unsafe { (self.vtable.clearer)(self.msg_ref.msg()) }
+        unsafe { (self.optional_vtable().clearer)(self.msg_ref.msg()) }
         self
     }
 }
@@ -446,7 +466,7 @@
         // SAFETY:
         // - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by
         //   the caller of `new`.
-        unsafe { (self.vtable.getter)(self.msg_ref.msg()) }
+        unsafe { (self.vtable().getter)(self.msg_ref.msg()) }
     }
 
     /// # Safety
@@ -455,7 +475,7 @@
         // SAFETY:
         // - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by
         //   the caller of `new`.
-        unsafe { (self.vtable.setter)(self.msg_ref.msg(), val) }
+        unsafe { (self.vtable().setter)(self.msg_ref.msg(), val) }
     }
 }
 
@@ -464,14 +484,14 @@
         // SAFETY:
         // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
         //   promised by the caller of `new`.
-        self.set(self.vtable.default)
+        self.set(self.optional_vtable().default)
     }
 
     pub(crate) fn set(self, val: T) -> Self {
         // SAFETY:
         // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
         //   promised by the caller of `new`.
-        unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val) }
+        unsafe { (self.optional_vtable().base.setter)(self.msg_ref.msg(), val) }
         self
     }
 
@@ -479,7 +499,7 @@
         // SAFETY:
         // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
         //   promised by the caller of `new`.
-        unsafe { (self.vtable.clearer)(self.msg_ref.msg()) }
+        unsafe { (self.optional_vtable().clearer)(self.msg_ref.msg()) }
         self
     }
 }