Allow Messages to be used in Oneofs.

PiperOrigin-RevId: 583347013
diff --git a/rust/test/shared/accessors_proto3_test.rs b/rust/test/shared/accessors_proto3_test.rs
index 3378ba6..945af2a 100644
--- a/rust/test/shared/accessors_proto3_test.rs
+++ b/rust/test/shared/accessors_proto3_test.rs
@@ -199,11 +199,23 @@
     assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0)));
     assert_that!(msg.oneof_field(), matches_pattern!(not_set(_)));
 
+    // TODO: the submessage api is still in progress so we can't yet
+    // cause a submsg to be set here.
+
+    // msg.oneof_nested_message_mut().or_default(); // Cause the nested_message
+    // field to become set.
+
+    // assert_that!(msg.oneof_bytes_opt(),
+    // eq(Optional::Unset(_))); assert_that!(msg.oneof_field(),
+    // matches_pattern!(OneofNestedMessage(_)));
+
     msg.oneof_uint32_set(Some(7));
     msg.oneof_bytes_mut().set(b"123");
     assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0)));
-
     assert_that!(msg.oneof_field(), matches_pattern!(OneofBytes(eq(b"123"))));
+
+    msg.oneof_bytes_mut().clear();
+    assert_that!(msg.oneof_field(), matches_pattern!(not_set(_)));
 }
 
 #[test]
diff --git a/src/google/protobuf/compiler/rust/oneof.cc b/src/google/protobuf/compiler/rust/oneof.cc
index 7f2671d..8335028 100644
--- a/src/google/protobuf/compiler/rust/oneof.cc
+++ b/src/google/protobuf/compiler/rust/oneof.cc
@@ -9,6 +9,7 @@
 
 #include <string>
 
+#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "google/protobuf/compiler/cpp/helpers.h"
 #include "google/protobuf/compiler/rust/context.h"
@@ -91,7 +92,9 @@
 }
 
 // TODO: Promote up to naming.h once all types can be spelled.
-std::string RsTypeName(const FieldDescriptor& desc) {
+std::string RsTypeName(Context<FieldDescriptor> field) {
+  const auto& desc = field.desc();
+
   // TODO: Fields with a ctype set not supported in v0.6 api.
   if (desc.options().has_ctype()) {
     return "";
@@ -99,6 +102,8 @@
 
   switch (desc.type()) {
     case FieldDescriptor::TYPE_MESSAGE:
+      return absl::StrCat("crate::", GetCrateRelativeQualifiedPath(
+                                         field.WithDesc(desc.message_type())));
     case FieldDescriptor::TYPE_ENUM:
     case FieldDescriptor::TYPE_GROUP:
       return "";
@@ -107,16 +112,16 @@
   }
 }
 
-std::string RsTypeNameView(const FieldDescriptor& desc) {
-  std::string type = RsTypeName(desc);
+std::string RsTypeNameView(Context<FieldDescriptor> field) {
+  std::string type = RsTypeName(field);
   if (type.empty()) return "";
-  return "View<'msg, " + type + ">";
+  return absl::StrCat("::__pb::View<'msg, ", type, ">");
 }
 
-std::string RsTypeNameMut(const FieldDescriptor& desc) {
-  std::string type = RsTypeName(desc);
+std::string RsTypeNameMut(Context<FieldDescriptor> field) {
+  std::string type = RsTypeName(field);
   if (type.empty()) return "";
-  return "Mut<'msg, " + type + ">";
+  return absl::StrCat("::__pb::Mut<'msg, ", type, ">");
 }
 
 }  // namespace
@@ -130,30 +135,30 @@
        {"view_fields",
         [&] {
           for (int i = 0; i < desc.field_count(); ++i) {
-            const auto& field = desc.field(i);
-            std::string rs_type = RsTypeNameView(*field);
+            const auto& field = *desc.field(i);
+            std::string rs_type = RsTypeNameView(oneof.WithDesc(field));
             if (rs_type.empty()) {
               continue;
             }
-            oneof.Emit({{"name", ToCamelCase(field->name())},
+            oneof.Emit({{"name", ToCamelCase(field.name())},
                         {"type", rs_type},
-                        {"number", std::to_string(field->number())}},
-                       R"rs($name$($pb$::$type$) = $number$,
+                        {"number", std::to_string(field.number())}},
+                       R"rs($name$($type$) = $number$,
                 )rs");
           }
         }},
        {"mut_fields",
         [&] {
           for (int i = 0; i < desc.field_count(); ++i) {
-            const auto& field = desc.field(i);
-            std::string rs_type = RsTypeNameMut(*field);
+            const auto& field = *desc.field(i);
+            std::string rs_type = RsTypeNameMut(oneof.WithDesc(field));
             if (rs_type.empty()) {
               continue;
             }
-            oneof.Emit({{"name", ToCamelCase(field->name())},
+            oneof.Emit({{"name", ToCamelCase(field.name())},
                         {"type", rs_type},
-                        {"number", std::to_string(field->number())}},
-                       R"rs($name$($pb$::$type$) = $number$,
+                        {"number", std::to_string(field.number())}},
+                       R"rs($name$($type$) = $number$,
                 )rs");
           }
         }}},
@@ -223,15 +228,15 @@
        {"view_cases",
         [&] {
           for (int i = 0; i < desc.field_count(); ++i) {
-            const auto& field = desc.field(i);
-            std::string rs_type = RsTypeNameView(*field);
+            const auto& field = *desc.field(i);
+            std::string rs_type = RsTypeNameView(oneof.WithDesc(field));
             if (rs_type.empty()) {
               continue;
             }
             oneof.Emit(
                 {
-                    {"case", ToCamelCase(field->name())},
-                    {"rs_getter", field->name()},
+                    {"case", ToCamelCase(field.name())},
+                    {"rs_getter", field.name()},
                     {"type", rs_type},
                 },
                 R"rs($Msg$_::$case_enum_name$::$case$ => $Msg$_::$view_enum_name$::$case$(self.$rs_getter$()),
@@ -241,31 +246,36 @@
        {"mut_cases",
         [&] {
           for (int i = 0; i < desc.field_count(); ++i) {
-            const auto& field = desc.field(i);
-            std::string rs_type = RsTypeNameMut(*field);
+            const auto& field = *desc.field(i);
+            std::string rs_type = RsTypeNameMut(oneof.WithDesc(field));
             if (rs_type.empty()) {
               continue;
             }
             oneof.Emit(
-                {
-                    {"case", ToCamelCase(field->name())},
-                    {"rs_mut_getter", field->name() + "_mut"},
-                    {"type", rs_type},
-                },
+                {{"case", ToCamelCase(field.name())},
+                 {"rs_mut_getter", field.name() + "_mut"},
+                 {"type", rs_type},
 
-                // The flow here is:
-                // 1) First find out which oneof field is already set (if any)
-                // 2) If a field is set, call the corresponding field's _mut()
-                // and wrap that Mut<> in the SomeOneofMut eum.
-                // During step 2 this code uses try_into_mut().unwrap() instead
-                // of .or_default() so that it will panic if step 1 says that
-                // the field is set, but then the _mut() accessor for the
-                // corresponding field shows as unset; if that happened it would
-                // imply a severe error in protobuf code; .or_default() would
-                // silently continue and cause the field to become set on the
-                // message, which is not the intended behavior.
+                 // Any extra behavior needed to map the mut getter into the
+                 // unwrapped Mut<>. Right now Message's _mut already returns
+                 // the Mut directly, but for scalars the accessor will return
+                 // an Optional which we then grab the mut by doing
+                 // .try_into_mut().unwrap().
+                 //
+                 // Note that this unwrap() is safe because the flow is:
+                 // 1) Find out which oneof field is already set (if any)
+                 // 2) If a field is set, call the corresponding field's _mut()
+                 // and wrap the result in the SomeOneofMut enum.
+                 // The unwrap() will only ever panic if the which oneof enum
+                 // disagrees with the corresponding field presence which.
+                 // TODO: If the message _mut accessor returns
+                 // Optional<> then this conditional behavior should be removed.
+                 {"into_mut_transform",
+                  field.type() == FieldDescriptor::TYPE_MESSAGE
+                      ? ""
+                      : ".try_into_mut().unwrap()"}},
                 R"rs($Msg$_::$case_enum_name$::$case$ =>
-               $Msg$_::$mut_enum_name$::$case$(self.$rs_mut_getter$().try_into_mut().unwrap()), )rs");
+               $Msg$_::$mut_enum_name$::$case$(self.$rs_mut_getter$()$into_mut_transform$), )rs");
           }
         }},
        {"case_thunk", Thunk(oneof, "case")}},