internal change

PiperOrigin-RevId: 1002449807
diff --git a/rust/codegen_traits.rs b/rust/codegen_traits.rs
index 8602c40..828b9f1 100644
--- a/rust/codegen_traits.rs
+++ b/rust/codegen_traits.rs
@@ -69,9 +69,14 @@
     type MessageMut<'msg>: MessageMut<'msg, Message = Self>;
 }
 
-/// A marker trait for messages that support reflection.
+/// A trait for messages that support reflection.
 #[cfg(not(lite_runtime))]
-pub trait WithReflection: Message + KernelWithReflection {}
+pub trait WithReflection: Message + KernelWithReflection {
+    /// Returns the fully-qualified name of the message, implemented by the kernel.
+    fn full_name() -> &'static str {
+        <Self as KernelWithReflection>::kernel_full_name(crate::__internal::Private)
+    }
+}
 
 /// A trait that all generated message views implement.
 #[diagnostic::on_unimplemented(
diff --git a/rust/cpp_kernel/reflection.cc b/rust/cpp_kernel/reflection.cc
index 9ce5e3a..deb8fd5 100644
--- a/rust/cpp_kernel/reflection.cc
+++ b/rust/cpp_kernel/reflection.cc
@@ -1,6 +1,7 @@
 #include <string>
 
 #include "absl/log/absl_check.h"
+#include "google/protobuf/descriptor.h"
 #include "google/protobuf/message.h"
 #include "google/protobuf/message_lite.h"
 #include "rust/cpp_kernel/strings.h"
@@ -8,6 +9,14 @@
 
 extern "C" {
 
+// Returns the full name of the message from its Descriptor.
+google::protobuf::rust::PtrAndLen proto2_rust_Descriptor_full_name(
+    const google::protobuf::Descriptor* desc) {
+  ABSL_CHECK(desc != nullptr) << "Descriptor is null.";
+  return google::protobuf::rust::PtrAndLen{desc->full_name().data(),
+                                 desc->full_name().size()};
+}
+
 // Converts a message to its TextFormat representation.
 google::protobuf::rust::RustStringRawParts proto2_rust_Message_print_to_text_format(
     const google::protobuf::MessageLite* m, bool single_line, bool hide_unknown_fields) {
diff --git a/rust/cpp_kernel/reflection.rs b/rust/cpp_kernel/reflection.rs
index 6ee19ac..c48b9fc 100644
--- a/rust/cpp_kernel/reflection.rs
+++ b/rust/cpp_kernel/reflection.rs
@@ -13,7 +13,15 @@
 
 use super::*;
 
-pub trait KernelWithReflection: MessageDescriptorInterop {}
+pub trait KernelWithReflection: MessageDescriptorInterop {
+    fn kernel_full_name(_private: Private) -> &'static str {
+        let desc = Self::__unstable_get_descriptor();
+        // SAFETY:
+        // - This function is only called via `WithReflection::full_name`. Gencode only implements
+        //   `WithReflection` for messages with reflection, so `desc` is a real descriptor.
+        unsafe { std::str::from_utf8_unchecked(proto2_rust_Descriptor_full_name(desc).as_ref()) }
+    }
+}
 impl<T: MessageDescriptorInterop> KernelWithReflection for T {}
 
 #[cfg(not(lite_runtime))]
@@ -21,6 +29,12 @@
     /// From reflection.cc
     ///
     /// # Safety
+    /// - `desc` points to a valid `proto2::Descriptor`.
+    fn proto2_rust_Descriptor_full_name(desc: *const std::ffi::c_void) -> PtrAndLen;
+
+    /// From reflection.cc
+    ///
+    /// # Safety
     /// - `m` is a legally dereferenceable MessageLite* that supports reflection.
     fn proto2_rust_Message_print_to_text_format(
         m: RawMessage,
diff --git a/rust/upb_kernel/reflection.rs b/rust/upb_kernel/reflection.rs
index 7e83b96..80009fa 100644
--- a/rust/upb_kernel/reflection.rs
+++ b/rust/upb_kernel/reflection.rs
@@ -20,7 +20,11 @@
 ///
 /// `UpbGetMessagePtr<Msg = Self>` ties the message pointer that reflection APIs operate on to the
 /// `MessageDef` they look up by `Self`, so the two can never describe different message types.
-pub trait KernelWithReflection: UpbWithReflection + UpbGetMessagePtr<Msg = Self> {}
+pub trait KernelWithReflection: UpbWithReflection + UpbGetMessagePtr<Msg = Self> {
+    fn kernel_full_name(_private: Private) -> &'static str {
+        Self::FULL_NAME
+    }
+}
 impl<T: UpbWithReflection + UpbGetMessagePtr<Msg = T>> KernelWithReflection for T {}
 
 /// Returns the protobuf TextFormat representation of `msg` with custom options.